2013-12-17 36 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