Substitution de Bash avec variable définie à partir d'un modèle global


10

L'exemple ci-dessous explique le problème. Pourquoi l' FILENAMEimpression est-elle correctement lorsqu'elle est répétée et perçue comme un motif lors de l'utilisation de la substitution?

#!/bin/bash

FILEPATH_WITH_GLOB="/home/user/file_*"
FILENAME=$(basename "$FILEPATH_WITH_GLOB")
echo $FILENAME                #file_1234
echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

Réponses:


15
FILEPATH_WITH_GLOB="/home/user/file_*"

Maintenant, FILEPATH_WITH_GLOBcontient/home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAMEcontient file_*.

echo $FILENAME                #file_1234

$FILENAMEétant non cité dans le contexte de la liste, cette expansion subit l'opérateur split + glob, de sorte qu'elle est étendue à la liste des fichiers correspondants: la génération du nom de fichier est effectuée lors de l' expansion des paramètres .

echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

Il s'agit toujours d'une extension de paramètre non citée dans le contexte de la liste, donc subit toujours split + glob. Cependant, ici, le ile_*modèle ne correspond à aucun fichier, il se développe donc à lui-même.

Ce que vous voulez probablement ici, c'est:

shopt -s nullglob # have globs expand to nothing when they don't match
set -- /home/user/file_* # expand that pattern into the list of matching 
                         # files in $1, $2...
for file do  # loop over them
  filename=$(basename -- "$file")
  printf '%s\n' "$filename" "${filename:1:5}"
done

Ou vous pouvez les stocker dans un tableau:

shopt -s nullglob
files=(/home/user/file_*)

Si vous ne vous souciez que de la première correspondance ou si vous savez qu'il n'y a qu'une seule correspondance, vous pouvez alors faire référence à ce fichier en tant que $files. basha ce comportement généralement ennuyeux qui se $filesdéveloppe à la ${files[0]}place de tous les éléments du tableau (un comportement hérité de ksh, fixé dans zsh), mais ici, ce serait un comportement souhaité pour une fois.


Merci pour l'explication. J'ai réussi à contourner ce problème FILEPATH_WITH_GLOB=`echo /home/user/file_*` après votre explication.
— TheMeaningfulEngineer

@Alan, c'est la mauvaise façon d'y remédier. Vous souhaitez utiliser un tableau ici. Soit les paramètres de position comme dans mon exemple (1 $, 2 $ ...) ou un bashtableau comme: files=(/home/user/file_*).
— Stéphane Chazelas

(et toutes les variables majuscules doivent vraiment être réservées aux variables d'environnement, echone doivent pas être utilisées pour des données arbitraires , les variables ne doivent pas être laissées sans guillemets dans les contextes de liste).
— Stéphane Chazelas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.