請幫我解決以下問題。\
n
從所有檔案中的 Test_Macro 中刪除所有字元對。請看下面的例子:
填寫1.txt
Test_Macro(abc, def, "\n string1 string2 \n test string",
"test string2 \n");
// Some code or text
Test_Macro(asdsadas, "test String1");
// Some code...
目錄1/檔案2.txt
Test_Macro(abc, def, "\n string1 string2 \n test string",
"test string2 \n",
123456);
// Some code or text
Test_Macro(asdsadas, "test String1");
// Some code...
預期結果:
文件1.txt
Test_Macro(abc, def, " string1 string2 test string",
"test string2 ");
// Some code or text
Test_Macro(asdsadas, "test String1");
// Some code...
目錄1/檔案2.txt
Test_Macro(abc, def, " string1 string2 test string",
"test string2 ",
123456);
// Some code or text
Test_Macro(asdsadas, "test String1");
// Some code...
非常感謝任何幫助或建議。我正計劃寫一些腳本。因為我有很多不同類型的文件和很多這樣的巨集。先致謝!
Test_Macro 的參數可以巢狀呼叫其他宏,並且可以在字串中包含任何字元。
答案1
有句話要記住,「正規表示式不能算」。
在這種情況下這一點很重要,因為許多「簡單」的 unix 工具都是基於正規表示式的。這裡的計數是對 Test_Macro 的參數中可能使用的左括號和右括號(「圓括號」)進行計數。
如果呼叫 Test_Macro絕不有嵌套的括號,那麼有一個簡單的技巧。首先將每個)
字元變更為換行符,反之亦然。然後刪除不包含 Test_Macro 的每一行,並刪除 Test_Macro 之前的所有內容。此時,處理後的 File2.txt 的一部分將如下所示
Test_Macro(abc, def, " string1 string2 test string",) "test string2 ",) 123456
所以現在我們需要轉換)
回來。此時您有幾個選擇。我贊成使用 sed 同時刪除多餘的空格。我們還需要添加回來,)
也許;
把這些放在一起,我們有
find . -type f | while read -r fn
do
< "$fn" tr ')\n' '\n)' | sed -n 's/.*Test_Macro(/Test_Macro(/p' | \
sed 's/) */ /g;s/$/);/'
done
如果 Test_Macro 的參數可能包含嵌套括號,那麼您需要拿出更大的槍,因為您需要解析輸入而不僅僅是模式匹配。 (理論上,如果您可以限制嵌套級別,那麼您可以進行模式匹配,但實際上這很快就會變得非常非常複雜,您應該放棄這種方法)。有針對 python 等語言的解析器框架,或者您可以在 lex 等工具之上建立工具。
答案2
編輯:這個答案是在問題修改之前準備好的。問題的原始形式包括:
當我嘗試使用“grep”查找某些模式時,它只會列印第一行。但我想要直到括號結束。
正規表示式不能計數,但 Sed 可以循環。
這是一個 Sed 片段,它將從任何包含Test_Macro
到具有適當右括號的行中抓取,即使有嵌套的括號:
#n
/Test_Macro/{
p;
:rep
s/([^()]*)//;
trep
/^[^(]*$/d;
h;
n;
p;
x;
G;
brep
}
轉換為單行程式碼,如下所示:
sed -n -e '/Test_Macro/{p;:rep' -e 's/([^()]*)//;trep' -e '/^[^(]*$/d;h;n;p;x;G;brep' -e '}'
輸入和輸出如下所示:
$ cat temp
Test_Macro(abc, def, "\n string1 string2 \n test string",
"test string2 \n");
// Some code or text
Test_Macro(asdsadas, "test String1");
// Some code...
$ sed -n -e '/Test_Macro/{p;:rep' -e 's/([^()]*)//;trep' -e '/^[^(]*$/d;h;n;p;x;G;brep' -e '}' temp
Test_Macro(abc, def, "\n string1 string2 \n test string",
"test string2 \n");
Test_Macro(asdsadas, "test String1");
$
答案3
文件1:
$ sed '/Test_Macro/{N;$!N;s/.*\(Test_Macro[^)]*);\).*/\1/;p;};d' abc.txt
Test_Macro(abc, def, "\n string1 string2 \n test string",
"test string2 \n");
Test_Macro(asdsadas, "test String1");
文件2:
$ sed '/Test_Macro/{N;$!N;s/.*\(Test_Macro[^)]*);\).*/\1/;p;};d' abc2.txt
Test_Macro(abc, def, "\n string1 string2 \n test string",
"test string2 \n",
123456);
Test_Macro(asdsadas, "test String1");
ps,刪除所有換行符的最簡單方法是;
echo -e "line \n break" | tr "\n" " "
沒有換行符;
$ sed ':a;N;$!ba;s/[^;]\n[ ]*/ /g;' abc2.txt | grep Test_Macro
Test_Macro(abc, def, "\n string1 string2 \n test string" "test string2 \n" 123456);
Test_Macro(asdsadas, "test String1");
沒有「\n」但有換行符號...哈哈
$ sed '/Test_Macro/{N;$!N;s/[ ]*\\n//g;s/.*\(Test_Macro[^)]*);\).*/\1/;p;};d' abc2.txt
Test_Macro(abc, def, " string1 string2 test string",
"test string2",
123456);
Test_Macro(asdsadas, "test String1");
只需刪除“\n”字串(和尾隨空格);
$ sed ':a;N;$!ba;s/\\n[ ]*//g;' abc2.txt
Test_Macro(abc, def, "string1 string2 test string",
"test string2 ",
123456);
// Some code or text
Test_Macro(asdsadas, "test String1");
// Some code...
再次(希望是最後一次)...在函數 Test_Macro 中刪除字串“\n”,但不在函數外部,並且不刪除換行符;
$ sed '{N;/Test_Ma/{s/[ ]*\\n//g;};s/\(Test_Macro[^)]*);\)/\1/};' abc2.txt
Test_Macro(abc, def, " string1 string2 test string",
"test string2",
123456);
// Some code or text \n
Test_Macro(asdsadas, "test String1");
// Some code...
更新;
$ sed '{:a;N;/Test_Ma/{s/[ ]*\\n//g;};ta};' abc2.txt
Test_Macro(abc, def, " string1 string2 test string",
"test string2",
"test string2",
"test string2",
"test string2",
"test string2",
"test string2",
"test string2",
"test string2",
"test string2",
"test string2",
"test string2",
123456);
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
Test_Macro(asdsadas, "test String1");
// Some code...