从文件中删除未知的特殊字符

我想从管道分隔文件中删除除|,_,-和.s以外的所有特殊字符。

例如,我的数据文件看起来像..

ABCD|123|Name
EFGH|456|New-Name
IJKL|789|New_Name
MNOP|123|New*name
QRST|124|New/name
UVWX|353|Name_*%NAME
EFGH|456|New=Name
Eaba|456|New****Name
fdsf|456|New-----Name
iouk|456|New(#$%^)_Name

我已经尝试了以下方法,但无法达到目标,或者只是一半。

tr -cd '[:print:]' < temp.txt > newfile -- I still get all the special chars.
tr -cd '[:alnum:]' <temp.txt -- I get only aphanum chars but I want to have a few special chars.
cat temp.txt | sed 's/[a-zA-Z0-9|_-.]//g' | sed '/^$/d' -- I get all the special chars but repetition is there

下面给出的输出为

$ cat temp.txt | sed 's/[a-zA-Z0-9|_-.]//g' | sed '/^$/d' | tr -cd '[:print:]' | sort -u
""""){***+#=**~>>\+*****<(")

如果我至少获得了所有唯一的特殊字符,则可以将所有内容放入sed并替换为null。

我的预期输出是:

ABCD|123|Name
EFGH|456|New-Name
IJKL|789|New_Name
MNOP|123|New_name
QRST|124|New_name
UVWX|353|Name_NAME
EFGH|456|New_Name
Eaba|456|New_Name
fdsf|456|New_Name
iouk|456|New_Name

如果需要帮助减少代码,则需要查看特定的列。如前所述,代码必须包含|,_,-字符并删除其他所有内容。 让我知道你们是否正在寻找更多信息。

qingfeng710 回答:从文件中删除未知的特殊字符

希望我能满足您的要求:

  1. -替换多个---(例如_)的组。
    (如果您的示例中有错字,只需删除此答案中的sed行。)
  2. 将所有字母,数字,|-以外的符号替换为_
  3. 重复挤压-_(例如----)。
  4. 在每个|分隔的字段中删除前导下划线。

以下脚本以相同的顺序实现这些要求(第一行是第一个要求,依此类推)。请注意,tr不是基于行的,并且像其他所有字符一样解释换行符,因此我们必须明确告诉tr保留换行符\n。另外请注意,-的参数中必须转义tr

f() {
     sed 's/---*/_/g' |
     tr -c  '[:alnum:]|\-\n' _ |
     tr -s  '\-_' |
     sed -E 's/(^|\|)_/\1/g'
}

像使用此功能

f  <infile  >outfile
,

听起来像“特殊字符”,是指非字母数字。如果是这样,则只需使用[:alnum:]字符类的取反来匹配那些字符,例如在每个UNIX框的任何外壳中的任何awk中,并且仅更改第3列,因为您说过“我需要查看特定的列”:

$ awk 'BEGIN{FS=OFS="|"} {gsub(/[^[:alnum:]-]+|--+/,"_",$3)} 1' file
ABCD|123|Name
EFGH|456|New-Name
IJKL|789|New_Name
MNOP|123|New_name
QRST|124|New_name
UVWX|353|Name_NAME
EFGH|456|New_Name
Eaba|456|New_Name
fdsf|456|New_Name
iouk|456|New_Name

如果[^[:alnum:]-]错误,则只需使用所需的任何字符类和/或列出特定字符[^*\/%-]。请注意,由于在|分隔的字段中没有|,因此您不需要在正则表达式中显式处理|

,

为什么不像这样:

sed -E 's/[*/_%=#()^$]+|-+/_/g' file
ABCD|123|Name
EFGH|456|New_Name
IJKL|789|New_Name
MNOP|123|New_name
QRST|124|New_name
UVWX|353|Name_NAME
EFGH|456|New_Name
Eaba|456|New_Name
fdsf|456|New_Name
iouk|456|New_Name
,

这可能对您有用(GNU sed):

sed -E 's/[^[:alnum:]|_.,*=/-]//g;s/[*=/]+/_/g;s/--+|__+/_/g' file

第一次替换会删除所有不需要的字符。

第二个替换用整个文件中的一个*替换了另外一个=/_

在整个文件中,第三次替换用单个-替换了两个或多个__

交替元字符|和替换定界符/可以在方括号表达式内表示其实际值,因此sed -E 's/[/|]//g' file将删除所有出现的/|。此外,方括号表达式中的-可以表示一个范围,[a-zA-Z0-9]表示与[[:alnum:]]等价的任何单个字母数字字符,但是如果将其放在右方括号之前,则表示其实数值,因此sed 's/[a-]//g' file将删除所有出现的a-

如果用户希望缩短那些多余的字符,则最终的替换可以修改为s/(-)-+|(_)_+/\1\2/g,它等效于s/--+/-/g;s/__+/_/g

,

这应该可以解决问题:

sed -r -e 's#([^a-zA-Z0-9\|_])+#_#g' -e 's/_+/_/g'

但是,您的预期输出与既定目标之间存在一些不一致之处。

特别是,您声明要保留连字符,但您将其保留在EFGH行上,但将其从fdsf行中删除。

,
  awk 'NR>2{sub(/New./,"New_")sub(/_..NAME/,"_NAME")sub(/_.*Name/,"_Name")}1' file
ABCD|123|Name
EFGH|456|New-Name
IJKL|789|New_Name
MNOP|123|New_name
QRST|124|New_name
UVWX|353|Name_NAME
EFGH|456|New_Name
Eaba|456|New_Name
fdsf|456|New_Name
iouk|456|New_Name
Eaba|456|New_Name
fdsf|456|New_Name
iouk|456|New_Name
本文链接:https://www.f2er.com/3124910.html

大家都在问