Text-Processing

正則表達式匹配一個字元的單個實例

  • October 6, 2021

我有一個我在工作中維護的東西,它使用了一個非常神秘的 DSL。而且它的工具不是很好。為了處理糟糕的工具,我編寫了一些腳本來嘗試在將程式碼發送到生產環境之前找出程式碼的一些問題。

我正在嘗試解決的目前問題與變數名有關。變數命名為@@Variable@@. 如果只有 1@或超過 2@秒,那麼這是一個致命錯誤。

現在我已經讓它遍歷有問題的文件,並在找到 3 個或更多連續的 ’s@@@時尋找並引發錯誤。@所以那部分很酷。

但我有點卡在單曲上@。一行中可以有多個變數。

@@Var1@@ words words words @@Var2@@  #This works
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

上面有很多排列,並且一行上的變數數量沒有限制。

如果任何給定行上只有一個變數,則此 awk 腳本有效,但如果一行上有超過 1 個變數,則此腳本無效。

awk '/@/ && ! /@@.*@@/' test.txt

我真正需要做的是匹配任何只有一個@. 在上面的範常式式碼中,它將匹配除第 1 行之外的所有行。

$ grep -E '(^|[^@])@([^@]|$)|@@@' file
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

或者:

$ awk '/(^|[^@])@([^@]|$)|@@@/' file
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

或一次分析一個欄位:

$ cat tst.awk
{
   for (i=1; i<=NF; i++) {
       if ( $i ~ /^@[^@]|[^@]@$|@@@/ ) {
           print "Failed line:", NR, $0
           print "\tbecause of field", i, $i
       }
   }
}
$ awk -f tst.awk file
Failed line: 2 @Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
       because of field 1 @Var1@@
Failed line: 3 @@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
       because of field 1 @@Var1@
Failed line: 4 @@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
       because of field 5 @Var2@@
Failed line: 5 @@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.
       because of field 5 @@Var2@

您不需要任何額外的東西來查找@@@案例,上述內容也包括查找該案例。

$ sed 'h;s/@@[^@ ]*@@//g;/@/!d;g' file
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

sed命令刪除有效的變數佔位符並報告仍包含@字元的行。它還會找到包含佔位符的行,其中@任一側有兩個以上。

我們可以通過將每條線保存到保留空間來報告原始故障線h。然後執行刪除潛在有效佔位符的替換,如果之後不包含任何@字元,我們將刪除該行。我們從保持空間中獲取原始行,g如果是,則列印它。

如果您的變數遵循與大多數程式語言相同的命名規則,則有效佔位符的模式@@[^@ ]*@@可以更改為。@@[[:alpha:]_][[:alnum:]_]*@@

假設您需要能夠@在文本本身中包含字元。在這種情況下,您需要@在上述命令中的替換之前刪除所有可能出現的不是變數佔位符的有效星座。


@一種更系統的方法是提取包含在一側或另一側具有太多字元的佔位符的行,刪除正確的行,然後將佔位符的行拉出,該佔位符@在變數名稱的任一側只有一個字元。

sed -e '/@\{3,\}[^@ ]*@\{1,\}/b' \
   -e '/@\{1,\}[^@ ]*@\{3,\}/b' \
   -e h \
   -e 's/@@[^@ ]*@@//g' \
   -e '/@[^@ ]*@/!d' \
   -e g file

以上將允許您的文本在@其他地方包含字元,因為它們不會以看起來像佔位符的模式出現。

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