2010-01-07 73 views
1
 
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等的用戶,只有像awk和sed這樣的標準Unix應用。如何從bash中的文本文件中提取子字符串?

 
Thanks, 
mossen 

回答

3

你想basename

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

哇,那真的很簡單。感謝你及時的答覆! – Mossen 2010-01-07 19:25:13

0

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

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

基名工作在一個文件/串在一個時間。如果你有很多字符串,你將迭代文件並多次調用外部命令。

用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" 
0

使用基名反覆有巨大的性能損失。當你在一個或兩個文件上做它時,它很小並且不明顯,但是它們會累加超過數百個。讓我爲你做一些時間測試,以說明爲什麼使用basneame(或任何系統util標註)在內部功能可以完成這項工作時很糟糕 - Dennis和ghostdog74爲您提供了更有經驗的BASH答案。

樣品輸入files.txt(我的完整路徑圖片列表):項

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代碼/術語編寫相同的功能,以完成工作,特別是一次又一次被稱爲很多次的工作。

相關問題