Sostituzione di Bash con variabile definita da un modello glob


10

L'esempio seguente spiega il problema. Perché la FILENAMEstampa viene eseguita correttamente quando viene ripetuta e percepita come uno schema quando si utilizza la sostituzione?

#!/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

Risposte:


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

Ora FILEPATH_WITH_GLOBcontiene/home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAMEcontiene file_*.

echo $FILENAME                #file_1234

$FILENAMEessendo non quotato nel contesto dell'elenco, quell'espansione subisce l'operatore split + glob, quindi viene espanso all'elenco del file corrispondente: la generazione del nome del file viene eseguita all'espansione dei parametri .

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

È ancora un'espansione dei parametri non quotata nel contesto dell'elenco, quindi subisce ancora split + glob. Tuttavia qui, il ile_*modello non corrisponde a nessun file, quindi si espande da solo.

Quello che probabilmente vuoi qui è:

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

Oppure puoi memorizzarli in un array:

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

Se ti interessa solo la prima corrispondenza o sai che esiste una sola corrispondenza, puoi fare riferimento a quel file come $files. bashha quel comportamento di solito fastidioso che si $filesespande ${files[0]}invece di tutti gli elementi dell'array (un comportamento ereditato da ksh, risolto in zsh), ma qui, sarebbe un comportamento desiderato per una volta.


Grazie per la spiegazione. Riuscito a risolvere il problema FILEPATH_WITH_GLOB=`echo /home/user/file_*` dopo la tua spiegazione.
TheMeaningfulEngineer,

@Alan, questo è il modo sbagliato di affrontarlo. Vuoi usare un array qui. In entrambi i parametri posizionali come nel mio esempio ($ 1, $ 2 ...) o un basharray di tipo: files=(/home/user/file_*).
Stéphane Chazelas,

(e tutte le variabili maiuscole dovrebbero davvero essere riservate alle variabili di ambiente, echonon dovrebbero essere utilizzate per dati arbitrari , le variabili non devono essere lasciate non quotate nei contesti degli elenchi).
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.