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
答案 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代码/术语中编写相同的功能以完成工作时,您真的希望避免对系统实用程序的任何外部调用,尤其是当它将被调用时很多次一遍又一遍。