替换除以下 ,.@ 之外的特殊字符

Replace special characters except the following ,.@

我正在寻找一个选项来从文件中删除除以下 3 项之外的特殊字符,。@

以下 awk 命令接近尾声,但它删除了所有标点符号。

awk '{gsub(/[[:punct:]]/,"",except(".","@",","))}1' test.csv > test2.csv

任何想法...

在 POSIX 中没有相反的字符 class 并且没有环顾四周来限制更通用的模式,但有一些例外。唯一的办法就是拼出POSIX字符class.

根据Character Classes and Bracket Expressions

‘[:punct:]’
Punctuation characters; in the ‘C’ locale and ASCII character encoding, this is ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ \ { | } ~.

您可以使用

/[!-+\/:-?[-`{-~-]/

参见regex demo

图例:

所有这 3 种方法都适用于任何语言环境,并且适用于任何字符 class,只需更改 class 名称,并且适用于其他括号表达式或字符串等:

1) 只需查找任何标点符号,但仅当它不是您不想更改的字符之一时才更改它:

$ echo 'a.b?c#d@e,f' |
awk '{
    new = ""
    while ( match([=10=],/[[:punct:]]/) ) {
        chr = substr([=10=],RSTART,1)
        new = new substr([=10=],1,RSTART-1) (chr ~ /[,.@]/ ? chr : "")
        [=10=]  = substr([=10=],RSTART+RLENGTH)
    }
    print new [=10=]
}'
a.bcd@e,f

2)先把不想改的字符转成其他字符串再转回去:

$ echo 'a.b?c#d@e,f' |
awk '{
    gsub(/a/,"aA"); gsub(/,/,"aB"); gsub(/\./,"aC"); gsub(/@/,"aD")
    gsub(/[[:punct:]]/,"")
    gsub(/aD/,"@"); gsub(/aC/,"."); gsub(/aB/,","); gsub(/aA/,"a")
    print
}'
a.bcd@e,f

a 更改为 aA 并返回可以保证您在转换 @ 等时创建的字符串是当时输入中其他地方不存在的字符串这就是为什么您之后可以安全地将它们转换回来的原因。

3) 用RS值作为后缀,然后从你不想改变的字符中删除RS后缀,然后改变剩余的RS后缀的标点:

$ echo 'a.b?c#d@e,f' |
awk '{
    gsub(/[[:punct:]]/,"&"RS)
    [=12=] = gensub("([,.@])"RS,"\1","g")
    gsub("[[:punct:]]"RS,"")
    print
}'
a.bcd@e,f

那个将 GNU awk 用于 gensub(),对于其他 awk,您需要 match()+substr()。