Как извлечь подстроку из текстового файла в Bash? - PullRequest
1 голос
/ 07 января 2010
I have lots of strings in a text file, like this:

"/home/mossen/Desktop/jeff's project/Results/FCCY.png"
"/tmp/accept/FLWS14UU.png"
"/home/tten/Desktop/.wordi/STSMLC.png"

Я хочу получить только имена файлов из строки, когда я читаю текстовый файл построчно, используя скрипт оболочки bash. Имя файла всегда будет заканчиваться на .png и всегда будет иметь перед собой символ "/". Я могу получить каждую строку в переменную, но каков наилучший способ извлечь имена файлов (FCCY.png, FLWS14UU.png и т. Д.) В переменные? Я не могу рассчитывать на пользователя, имеющего Perl, Python и т. Д., Только стандартные утилиты Unix, такие как awk и sed.

Thanks,
mossen

Ответы [ 5 ]

3 голосов
/ 07 января 2010

Вы хотите basename:

$ basename /tmp/accept/FLWS14UU.png
FLWS14UU.png
1 голос
/ 08 января 2010

basename работает с одним файлом / строкой за раз. Если у вас много строк, вы будете повторять файл и вызывать внешнюю команду много раз.

используйте awk

$ awk -F'[/"]' '{print $(NF-1)}' file
FCCY.png
FLWS14UU.png
STSMLC.png

или используйте оболочку

while read -r line
do
    line=${line##*/}
    echo "${line%\"}"
done <"file"
0 голосов
/ 10 января 2010

Повторное использование базового имени имеет огромный удар по производительности. Он маленький и незаметный, когда вы делаете это над файлом или двумя, но складывает более сотни из них. Позвольте мне сделать несколько временных тестов, чтобы вы продемонстрировали, почему использование basneame (или любого вызова системной утилиты) плохо, когда внутренняя функция может выполнить эту работу - Деннис и ghostdog74 дали вам более опытные ответы BASH.

Пример входных файлов files.txt (список моих фото с полным путем): 3749 записи

external.sh

while read -r line
do
  line=`basename "${line}"`
  echo "${line%\"}"
done < "files.txt"

internal.sh

while read -r line
do
  line=${line##*/}
  echo "${line%\"}"
done < "files.txt"

Результаты по времени, перенаправляя вывод в / dev / null, чтобы избавиться от задержки видео:

$ time sh external.sh 1>/dev/null 

real   0m4.135s
user   0m1.142s
sys    0m2.308s

$ time sh internal.sh 1>/dev/null 

real   0m0.413s
user   0m0.357s
sys    0m0.021s

Вывод обоих идентичен:

$ sh external.sh | sort > result1.txt
$ sh internal.sh | sort > result2.txt
$ diff -uN result1.txt result2.txt

Итак, как вы можете видеть из временных тестов, вы действительно хотите избежать любых внешних вызовов системных утилит, когда вы можете написать ту же функцию в каком-нибудь творческом коде BASH / жаргоне, чтобы выполнить работу, особенно когда она будет вызвана много раз снова и снова.

0 голосов
/ 07 января 2010
$ var="/home/mossen/Desktop/jeff's project/Results/FCCY.png"
$ file="${var##*/}"
0 голосов
/ 07 января 2010

newlist=$(for file in ${list} ;do basename ${file}; done)

...