我試圖刪除文件名中的空格並替換它們。sed/awk - 刪除文件名中的空格
輸入:
echo "File Name1.xml File Name3 report.xml" | sed 's/[[:space:]]/__/g'
但是輸出
File__Name1.xml__File__Name3__report.xml
所需的輸出
File__Name1.xml File__Name3__report.xml
我試圖刪除文件名中的空格並替換它們。sed/awk - 刪除文件名中的空格
輸入:
echo "File Name1.xml File Name3 report.xml" | sed 's/[[:space:]]/__/g'
但是輸出
File__Name1.xml__File__Name3__report.xml
所需的輸出
File__Name1.xml File__Name3__report.xml
您在問題的標題中名爲awk
,不是嗎?
$ echo "File Name1.xml File Name3 report.xml" | \
> awk -F'.xml *' '{for(i=1;i<=NF;i++){gsub(" ","_",$i); printf i<NF?$i ".xml ":"\n" }}'
File_Name1.xml File_Name3_report.xml
$
-F'.xml *'
指示awk
分裂上的正則表達式,所請求的擴展加上0或多個空格{for(i=1;i<=NF;i++)
被用於其中輸入線(s)是所有字段執行(是)分裂 - 注意,最後一個字段是無效的(這是接下來的最後一個擴展名),但我們要考慮到這一點... gsub(" ","_", $i)
替代的空間所有出現在當前領域強調,通過循環變量作爲索引i
printf i<NF?$i ".xml ":"\n"
輸出不同的東西,如果i<NF
它是一個普通的領域,所以我們追加擴展和一個空格,否則i
等於NF
,我們只想用換行符終止輸出行。它並不完美,其追加的最後一個文件名之後的空間。我希望這足夠好...
▶一個d d簡d U m的◀
我想解決:
awk
爲了達到這些目標,我決定換一個殼功能的小腳本,即改變空格爲下劃線被命名爲s2u
$ s2u() { awk -F'\.'$1' *' -v ext=".$1" '{
> NF--;for(i=1;i<=NF;i++){gsub(" ","_",$i);printf "%s",$i ext (i<NF?" ":"\n")}}'
> }
$ echo "File Name1.xml File Name3 report.xml" | s2u xml
File_Name1.xml File_Name3_report.xml
$
這是一個有點不同(更好?)「CS它不是特殊打印最後一個字段,而是特殊情況下每個字段附加的分隔符,但擴展名分割的想法仍然存在。
感謝您的詳細解答,我已經學到了很多:) – Deano
由於未加密的三元表達式,這將導致某些awk中的語法錯誤,並且當文件名包含printf格式化字符時,它將以加密方式失敗。 'big%slip.xml' - 總是使用'printf'%s「,$ i'而不是'printf $ i'。您可能希望使用'[[:space:]]「,而不是對希望/假定ORS的值進行硬編碼,而是在printf的末尾逐字使用'ORS'而不是'\ n」'。 +'而不是''''-F和gsub正則表達式。 –
有些'awk's沒有正則表達式字符類......我不想使用默認的'ORS',我想要一個換行符!也就是說,我已經在三元表達式中實現了關於括號的建議,正確使用了'printf',也糾正了最後一個空白的bug。 TX – gboffi
這似乎是一個很好的開始,如果文件名不劃定:
((?:\S.*?)?\.\w{1,})\b
( // start of captured group
(?: // non-captured group
\S.*? // a non-white-space character, then 0 or more any character
)? // 0 or 1 times
\. // a dot
\w{1,} // 1 or more word characters
) // end of captured group
\b // a word boundary
您必須查看PCRE模式如何轉換爲shell模式。或者,它可以從Python/Perl/PHP腳本運行。
你可以使用rename
:
rename --nows *.xml
這將替換XML文件的所有空間在當前文件夾用_
。
有時是不帶--nows
選項,這樣你就可以使用搜索和替換:
rename 's/[[:space:]]/__/g' *.xml
最終,你可以使用--dry-run
,如果你只想打印文件名,而無需編輯的名字。
假設您要求如何重命名文件名,並且不要刪除因某種其他原因而使用的文件名列表中的空格,這是漫長而短暫的。很長的路使用sed。短路使用重命名。如果你不想重命名文件,你的問題還不清楚,應該修改。
如果目標是簡單地獲取xml文件名列表並用sed更改它們,則底層示例是如何執行該操作。
目錄內容:
ls -w 2
bob is over there.xml
fred is here.xml
greg is there.xml
cd [directory with files]
shopt -s nullglob
a_glob=(*.xml);
for ((i=0;i< ${#a_glob[@]}; i++));do
echo "${a_glob[i]}";
done
shopt -u nullglob
# output
bob is over there.xml
fred is here.xml
greg is there.xml
# then rename them
cd [directory with files]
shopt -s nullglob
a_glob=(*.xml);
for ((i=0;i< ${#a_glob[@]}; i++));do
# I prefer 'rename' for such things
# rename 's/[[:space:]]/_/g' "${a_glob[i]}";
# but sed works, can't see any reason to use it for this purpose though
mv "${a_glob[i]}" $(sed 's/[[:space:]]/_/g' <<< "${a_glob[i]}");
done
shopt -u nullglob
結果:
ls -w 2
bob_is_over_there.xml
fred_is_here.xml
greg_is_there.xml
通配的是你想在這裏,因爲在名稱空間的什麼。
然而,這的確是一個複雜的解決方案,而實際上所有你需要做的是:
cd [your space containing directory]
rename 's/[[:space:]]/_/g' *.xml
,就是這樣,你就大功告成了。
另一方面,如果你正在嘗試創建一個文件名列表,你肯定會想要globbing方法,如果你只是修改語句,也會做你想做的事情,也就是使用sed更改輸出文件名稱。
如果你的目標是要改變文件名進行輸出的目的,而不是重命名的實際文件:
cd [directory with files]
shopt -s nullglob
a_glob=(*.xml);
for ((i=0;i< ${#a_glob[@]}; i++));do
echo "${a_glob[i]}" | sed 's/[[:space:]]/_/g';
done
shopt -u nullglob
# output:
bob_is_over_there.xml
fred_is_here.xml
greg_is_there.xml
哪裏有文件名來自何處?可以指示Awk對換行符進行分隔,然後可以更容易地在模式中進行匹配。 – linden2015
文件名是否具有相同的'.xml'擴展名? –
是的,他們都是'.xml'文件 – Deano