Shell-Script
正則表達式不匹配的 for 循環和定位命令
當我更改任何配置時,我製作了後綴為 .original 的原始文件的副本。現在我正在編寫一個簡單的腳本,它將查找所有 *.original 文件並使用這兩個版本,即帶有和不帶有 .original 後綴的版本。
我確實使用
locate
帶有正則表達式的命令來避免original
路徑中間的字元串不匹配的文件。我的命令是
locate --regex ^.*\\.original$
完美in terminal
的。它會查找所有以 .original 後綴結尾的文件,例如file.original
但是,當我在中使用相同的命令
in bash script
時,for loop
它會返回諸如file.original
file-original
file_original
等之類的變體。我應該如何修改正則表達式或 for 循環以僅獲取 .original 文件?
我的外殼是:
$ echo $BASH /usr/bin/bash
我的 bash 腳本是:
#!/usr/bin/bash echo "Plain locate command:" locate --regex ^.*\\.original$ | grep test echo "For loop:" for file in `locate --regex ^.*\\.original$ | grep test`; do echo $file done
您可以使用它進行測試:
mkdir /tmp/test touch /tmp/test/file.original touch /tmp/test/file-original touch /tmp/test/file_original updatedb locate --regex ^.*\\.original$
在我的終端中,它會發現:
/tmp/test/file.original
但我的腳本會發現:
Plain locate command: /tmp/test/file.original For loop: /tmp/test/file-original /tmp/test/file.original /tmp/test/file_original
反引號需要更多的轉義。這是您應該更喜歡的原因之一
$()
(例如,請參閱此答案中的“反斜杠樂趣”:和之間有什麼區別?`$(stuff)```stuff``)。由於反引號內沒有足夠的轉義,當字元串最終被解釋為正則表達式時,您想要轉義的點不會被轉義。
將相關行更改為:
for file in $(locate --regex '^.*\.original$' | grep test); do
筆記:
- 我使用單引號來方便地處理反斜杠和星號。在您的原始程式碼中,未引用和未轉義的星號可以觸發文件名擴展。
^.*
在正則表達式中沒有任何改變。單引號\.original$
就足夠了。我決定保留^.*
只是為了指出文件名擴展的可能性。- 習慣於引用變數(例如
echo "$file"
)。連結的答案$()
也建議引用,但在我們的for
循環中引用是錯誤的。不引用$()
也是錯誤的。兩者都是錯誤的,因為……- 一般來說,像這樣建構
for
循環通常是錯誤的。這是Bash 的第一個陷阱。locate
用更好的管道輸出做一些事情toxargs
,最好是空終止的字元串:locate -0 … | grep -z … | xargs -r0 …
這些選項不可移植。