如何从bash中的文本文件中提取子字符串?

时间:2010-01-07 19:15:54

标签: string bash shell extract filenames

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 shell脚本逐行读取文本文件时,只获取字符串中的文件名。文件名将始终以.png结尾,并且前面总是有“/”。我可以将每个字符串都变成var,但是将文件名(FCCY.png,FLWS14UU.png等)提取到变量中的最佳方法是什么?我不能指望拥有Perl,Python等用户,只需要标准的Unix工具,如awk和sed。

Thanks,
mossen

5 个答案:

答案 0 :(得分:3)

您想要basename

$ basename /tmp/accept/FLWS14UU.png
FLWS14UU.png

答案 1 :(得分:1)

basename一次只能处理一个文件/字符串。如果你有很多字符串,你将迭代文件并多次调用外部命令。

使用awk

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

或使用shell

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

$ var="/home/mossen/Desktop/jeff's project/Results/FCCY.png"
$ file="${var##*/}"

答案 4 :(得分:0)

迭代地使用basename会带来巨大的性能损失。当你在一两个文件上做它时,它很小而且不明显,但却增加了数百个。让我为你做一些计时测试,以举例说明为什么在内部功能可以完成这项工作时使用basneame(或任何系统util callout)是不好的 - Dennis和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代码/术语中编写相同的功能以完成工作时,您真的希望避免对系统实用程序的任何外部调用,尤其是当它将被调用时很多次一遍又一遍。