2013-12-17 94 views
1

我試圖獲取帶有特殊字符的行不帶前綴\。下面是特殊字符:刪除特定字符與給定模式的線條

^$%.*+?!(){}[]|\ 

我需要檢查所有未在第2列與\前綴上述特殊字符。我試圖用awk來完成這個,但沒有運氣。我想要輸出如下。

input.txt中

1,ap^ple 
2,o$range 
3,bu+tter 
4,gr(ape 
5,sm\(ok\e 
6,ra\in 
7,p+la\\y 
8,wor\+k 

output.txt的

1,ap^ple 
2,o$range 
3,bu+tter 
4,gr(ape 
5,sm\(ok\e 
6,ra\in 
7,p+la\\y 

第七行和第5行是在output.txt的,因爲有2個特別charcters(一種是與反斜槓另一個無反斜槓)

+0

是否應該輸出包含「\\\」的行?爲什麼? –

回答

1

您可以嘗試以下操作:

awk ' 
{ 
    line=$0 
    sub(/\\[\^$%.*+?!(){}\[\]|\\]/,"") 
    if(/[\^$%.*+?!(){}\[\]|\\]/) 
     print line 
}' input.txt 
2

「最終」最終編輯:我想允許「\ x」無論x是什麼,但OP似乎不想要,所以我也修正了它。

試圖找到一個「聰明」的正則表達式後(其中嗆「\\」或「\」任何有奇數,但顯然就職於休息...)

我重新寫在AWK做一個「狀態自動機」的方式:

的想法:

如果「正常模式」,我們遇到的不是「\」以外的特殊字符? :我們打印行! 如果在「正常模式」下遇到「\」? :我們進入「逃脫模式」,並在該模式下,忽略下一個字符 (但如果我們沒有下一個字符,我們需要打印該行呢!)

腳本:

awk -F"," ' 
    { 
    IN_ESCAPED_MODE=0 ; 
    for (i=1 ; i<=length($2) ; i++) 
    { char=substr($2,i,1) 

     if (IN_ESCAPED_MODE == 0) 
    { if (index(".^$%*+?!(){}[]|",char) > 0) 
      { print $0 ; break ; 
      } 

      if (index("\\" , char) > 0) 
      { IN_ESCAPED_MODE=1 ; continue ; 
      } 
     } 

     if (IN_ESCAPED_MODE == 1) 
    { if (index(".^$%*+?!(){}[]|\\",char) > 0) 
      { IN_ESCAPED_MODE=0 ; continue ; 
       } 
      else 
       { IN_ESCAPED_MODE=0 ; print $0; break; 
       } 
     } 
    } 

    if (IN_ESCAPED_MODE == 1) 
    { 
     print $0 ; break ; 
    } 

    } 
' input.txt > output.txt 

有了這個改變,你將會得到與OP相同的輸出,例如當它包含「\ e」時打印出一行......我覺得很奇怪:對我來說「\ e」很好,我們可以「逃避「什麼?

與該輸入:

1,ap^ple 
2,o$range 
3,bu+tter 
4,gr(ape 
5,sm\(ok\e 
6,ra\in 
7,p+la\\y 
8,wor\+k 

10,\ 
11,\\ 
12,\\\ 
13,. 
14,\. 
15,.. 
16,^ 
17,\^ 
18,$ 
19,\$ 
20,% 
21,\% 
22,* 
23,\* 
24,+ 
25,\+ 
26,? 
27,\? 
28,! 
29,\! 
30,(
31,\(
32,) 
33,\) 
34,{ 
35,\{ 
36,} 
37,\} 
38,[ 
39,\[ 
40,] 
41,\] 
42,| 
43,\| 

它輸出:

1,ap^ple 
2,o$range 
3,bu+tter 
4,gr(ape 
5,sm\(ok\e 
6,ra\in 
7,p+la\\y 
10,\ 
12,\\\ 
13,. 
15,.. 
16,^ 
18,$ 
20,% 
22,* 
24,+ 
26,? 
28,! 
30,(
32,) 
34,{ 
36,} 
38,[ 
40,] 
42,| 

(所以它看起來真的管用這一次!)

如果你喜歡讓任何 「\ X」,而不是僅在 「X」 是一個特殊字符:

改變 「中間線」:

 if (IN_ESCAPED_MODE == 1) 
     { if (index(".^$%*+?!(){}[]|\\",char) > 0) 
      { IN_ESCAPED_MODE=0 ; continue ; 
      } 
      else 
      { IN_ESCAPED_MODE=0 ; print $0; break; 
      } 
     } 

到:

 if (IN_ESCAPED_MODE == 1) 
     { IN_ESCAPED_MODE=0 ; continue ; 
     } 

的歷史原因:正則表達式(如果有「\\」,它曾在「最」的情況,但在有些哽咽,例如):

egrep '[^\][].^$%*+?!(){}[|]|[^\][\][^].^$%*+?!(){}[|\]' input.txt > output.txt 

但是,一個不顯示12行,例如...

很好看的:http://www.regular-expressions.info/charclass.html ....和http://www.gnu.org/software/gawk/manual/html_node/Gory-Details.html(可怕......)

+0

sed輸出與input.txt相同 – Marjer

+0

@GanzRicanz:我忘了'<'。 thx –

+1

還是沒有什麼區別,我可以在output.txt – Marjer

1
sed '/[]\\^$%.*+?!(){}[|]/ { 
    h 
    s/\\[]\\^$%.*+?!(){}[|]/_/g 
    /[]\\^$%.*+?!(){}[|]/ { 
    x 
    p 
    } 
    }' YourFile 

根據殼和sed可以不同地解釋(特別是\)。適用於我的AIX/KSH