Bash-Substitution mit einer aus einem Glob-Muster definierten Variablen


10

Das folgende Beispiel erläutert das Problem. Warum wird der FILENAMEAusdruck korrekt gedruckt, wenn er bei Verwendung der Substitution als Muster wiedergegeben und wahrgenommen wird?

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

Antworten:


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

Jetzt FILEPATH_WITH_GLOBenthält/home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAMEenthält file_*.

echo $FILENAME                #file_1234

$FILENAMEDa diese Erweiterung im Listenkontext nicht in Anführungszeichen gesetzt ist, wird sie dem Operator split + glob unterzogen, sodass sie auf die Liste der übereinstimmenden Dateien erweitert wird: Die Generierung des Dateinamens erfolgt bei der Parametererweiterung .

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

Es handelt sich immer noch um eine nicht zitierte Parametererweiterung im Listenkontext, daher wird immer noch split + glob durchgeführt. Hier ile_*stimmt das Muster jedoch nicht mit einer Datei überein, sodass es stattdessen auf sich selbst erweitert wird.

Was Sie hier wahrscheinlich wollen, ist:

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

Oder Sie können sie in einem Array speichern:

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

Wenn Sie sich nur für die erste Übereinstimmung interessieren oder wissen, dass es nur eine Übereinstimmung gibt, können Sie auf diese Datei als verweisen $files. bashhat das normalerweise nervige Verhalten, das $filessich auf ${files[0]}alle Elemente des Arrays ausdehnt (ein Verhalten, das von geerbt kshund behoben wurde zsh), aber hier wäre das einmal ein gewünschtes Verhalten.


Danke für die Erklärung. Hat es geschafft, FILEPATH_WITH_GLOB=`echo /home/user/file_*` nach Ihrer Erklärung eine Problemumgehung durchzuführen.
TheMeaningfulEngineer

@ Alan, das ist der falsche Weg, um es anzusprechen. Sie möchten hier ein Array verwenden. Entweder die Positionsparameter wie in meinem Beispiel ($ 1, $ 2 ...) oder ein bashArray wie : files=(/home/user/file_*).
Stéphane Chazelas

(und alle Variablen in Großbuchstaben sollten wirklich für Umgebungsvariablen reserviert sein, echosollten nicht für beliebige Daten verwendet werden , Variablen sollten in Listenkontexten nicht unzitiert bleiben).
Stéphane Chazelas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.