我想从管道分隔文件中删除除|,_,-和.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
如果需要帮助减少代码,则需要查看特定的列。如前所述,代码必须包含|,_,-字符并删除其他所有内容。 让我知道你们是否正在寻找更多信息。
答案 0 :(得分:3)
希望我能满足您的要求:
-
替换多个---
(例如_
)的组。sed
行。) |
和-
以外的符号替换为_
。-
和_
(例如---
→-
)。|
分隔的字段中删除前导下划线。以下脚本以相同的顺序实现这些要求(第一行是第一个要求,依此类推)。请注意,tr
不是基于行的,并且像其他所有字符一样解释换行符,因此我们必须明确告诉tr
保留换行符\n
。另外请注意,-
的参数中必须转义tr
。
f() {
sed 's/---*/_/g' |
tr -c '[:alnum:]|\-\n' _ |
tr -s '\-_' |
sed -E 's/(^|\|)_/\1/g'
}
像使用此功能
f <infile >outfile
答案 1 :(得分:2)
听起来像“特殊字符”,是指非字母数字。如果是这样,则只需使用[: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:]-]
错误,则只需使用所需的任何字符类和/或列出特定字符[^*\/%-]
。请注意,由于在|
分隔的字段中没有|
,因此您不需要在正则表达式中显式处理|
。
答案 2 :(得分:1)
为什么不像这样:
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
答案 3 :(得分:0)
这可能对您有用(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
。
答案 4 :(得分:0)
这应该可以解决问题:
sed -r -e 's#([^a-zA-Z0-9\|_])+#_#g' -e 's/_+/_/g'
但是,您的预期输出与既定目标之间存在一些不一致之处。
特别是,您声明要保留连字符,但您将其保留在EFGH行上,但将其从fdsf行中删除。
答案 5 :(得分:-1)
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