Shell-Script

正則表達式不匹配的 for 循環和定位命令

  • April 8, 2021

當我更改任何配置時,我製作了後綴為 .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用更好的管道輸出做一些事情to xargs,最好是空終止的字元串:
locate -0 … | grep -z … | xargs -r0 …

這些選項不可移植。

引用自:https://unix.stackexchange.com/questions/644060