Grep

在 grep 中轉義基本/擴展 posix 正則表達式字元串中的元字元

  • February 22, 2012

是否可以在將變數傳遞給 grep 之前轉義變數內字元串的所有元字元?我知道之前在 SE(這裡)上已經問過類似的問題,這裡也有一個很好的解釋,但我只是好奇是否可以使用基本/擴展 posix 正則表達式模式而不是 perl 模式?(目前我正在閱讀 perl 正則表達式語法以首先理解它,而不是跳入解決方案)

**為什麼這個要求:(**元,不需要回答)

我正在嘗試編寫一個小腳本來拆分大文件,在其中將文件拆分為file_name.ext.000, file_name.ext.001… 等,效果很好。現在我不喜歡拆分那些已經拆分的文件(即,文件名具有 3 個字元副檔名,都是數字,它們的大小總和為原始文件大小。現在,如果我也使用類似的普通 shellfile_name.ext.*擴展匹配具有的文件file_name.ext.ext2,因此即使不需要重新拆分,也會發生總大小不匹配和拆分。所以我只會檢查那些名稱為數字的文件file_name.ext.######我目前查找這些部分的文件大小的表達式如下所示:

FILE_SIZE_EXISTING=$( (find "$DESTINATION" -type f -regextype posix-extended -regex "^$DESTINATION/$FILE_BASENAME(\.[[:digit:]]{3})?$" -print0 | xargs -0 stat --printf="%s\\n" 2>/dev/null || echo 0) | paste -sd+ | bc)

這適用於簡單的文件名。但是,如果某些花哨的名稱例如包含

$$ $$ 等有解決方法嗎?我是 shell 腳本的新手,因此不太了解 perl。

如何引用特殊字元(可移植)

以下程式碼片段在擴展正則表達式中特殊的每個字元之前添加了一個反斜杠,sed用於將任何出現的字元替換為][()\.^$?*+後跟該字元的反斜杠:

raw_string='test[string]\.wibble'
quoted_string=$(printf %s "$raw_string" | sed 's/[][()\.^$?*+]/\\&/g')

$raw_string這將刪除;中的尾隨換行符 如果這是一個問題,請通過在末尾添加一個惰性字元來確保字元串不以換行符結尾,然後刪除該字元。

quoted_string=$(printf %sa "$raw_string" | sed 's/[][()\.^$?*+]/\\&/g')
quoted_string=${quoted_string%?}

如何引用特殊字元(在 bash 或 zsh 中)

Bash 和 zsh 有一個模式替換功能,如果字元串不是很長,它可以更快。這裡比較麻煩,因為替換必須是字元串,所以每個字元都需要單獨替換。請注意,您必須先轉義反斜杠。

quoted_string=${raw_string//\\//\\\\}
for c in \[ \] \( \) \. \^ \$ \? \* \+; do
 quoted_string=${quoted_string//"$c"/"\\$c"}
done

如何引用特殊字元(在 ksh93 中)

Ksh 的字元串替換構造比 bash 和 zsh 中的淡化版本更強大。它支持對模式中的組的引用。

quoted_string=${raw_string//@([][()\.^$?*+])/\\\1}

你真正想要的

您不需要find這裡:shell 模式足以匹配以三位數字結尾的文件。如果不存在零件文件,則 glob 模式將保持未展開狀態。還有一種更簡單的添加文件大小的方法:而不是使用stat(存在於許多 unix 變體中,但每個變體都有不同的語法)並執行複雜的流水線來對值求和,您可以呼叫wc -c(在正常文件上,在大多數係統上,wc將查看文件大小而不費心打開文件並讀取字節)。

set -- "$DESTINATION/$FILE_BASENAME".[0-9][0-9][0-9]
case $1 in
 *\]) # The glob was left intact, so no part exists
   do_split …;;
 *) # The glob was expanded, so at least one part exists
   FILE_SIZE_EXISTING=$(wc -c "$@" | sed -n '$s/[^0-9]//gp')
   if [ "$FILE_SIZE_EXISTING" -ne "$(wc -c <"$DESTINATION/$FILE_BASENAME")" ]; then
     do_split …
   fi

請注意,您對總大小的測試不是很可靠:如果文件已更改但大小保持不變,您最終會得到陳舊的部分。如果文件永遠不會更改,那沒關係,唯一的風險是部分可能會被截斷或失去。

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