Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 从文件中删除未知的特殊字符_Bash_Unix_Awk_Sed - Fatal编程技术网

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

Bash 从文件中删除未知的特殊字符,bash,unix,awk,sed,Bash,Unix,Awk,Sed,我想删除管道分隔文件中除|、,-和.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 我已经尝试了下面的方法,但没

我想删除管道分隔文件中除|、,-和.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
如果这有助于减少代码,我需要查看特定的列。如前所述,代码必须包含|、,-个字符,并删除所有其他字符。
如果你们想了解更多信息,请告诉我

我希望我没有弄错您的要求:

  • 将多组
    -
    (例如
    -
    )替换为
    .

    (如果您的示例中有输入错误,只需删除此答案中的
    sed
    行即可。)
  • 将字母、数字、
    |
    -
    以外的所有符号替换为
  • 重复挤压
    -
    -
    (例如
    -
    → <代码>-)
  • 删除每个
    |
    分隔字段中的前导下划线
  • 以下脚本以相同的顺序实现这些需求(第一行表示第一个需求,依此类推)。请注意,
    tr
    不是基于行的,并且像其他字符一样解释换行符,因此我们必须明确告诉
    tr
    以保留换行符
    \n
    。还要注意,
    -
    必须在
    tr
    的参数中转义

    f() {
         sed 's/---*/_/g' |
         tr -c  '[:alnum:]|\-\n' _ |
         tr -s  '\-_' |
         sed -E 's/(^|\|)_/\1/g'
    }
    
    像这样使用这个函数

    f  <infile  >outfile
    
    f输出文件
    
    为什么不仅仅是一些这样的人:

    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
    
    听起来“特殊字符”是指非字母数字。如果是这样,那么只需使用
    [:alnum:://code>字符类的否定来匹配这些字符,例如,在每个UNIX框的任何shell中使用任何awk,并且只更改第3列,因为您说过“我需要查看特定列”:

    如果
    [^[:alnum::]
    错误,则只需使用所需的字符类和/或列出特定字符
    [^*\/%-]
    。请注意,您不需要在regexps中显式地处理
    ,因为在
    分隔字段中不能有

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

    第一次替换将删除任何不需要的字符

      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
    
    第二个替换用整个文件中的一个
    .
    =
    /
    替换另一个
    .

    第三个替换将整个文件中的两个或多个
    -
    替换为一个

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


    最后的替换可以修改为
    s/(-)+|(-)+/\1\2/g
    ,相当于
    s/-+/-/g;如果用户希望缩短那些多余的字符,请使用s/_+/g

    这应该可以做到:

      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
    
    sed -r -e 's#([^a-zA-Z0-9\|_])+#_#g' -e 's/_+/_/g'
    
    然而,您的预期输出和声明的目标之间存在一些不一致


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

    谢谢@Socowi。这几乎没问题。我仍然得到——应该删除/替换。而且,我不知道我将得到什么特殊字符。所以我需要得到列表并相应地替换它们。嗯,你不是说保留
    -
    字符吗<代码>---
    只是其中的4个。是的。我只想保留1-。但不是——:)啊,对不起。我应该多注意你的小例子。添加了一个命令,用
    -
    替换
    -
    。但是你所说的
    是什么意思?我不知道我会得到什么特殊字符?您只需指定要保留的内容。所有其他字符都已删除。第二个输出行与发布的预期输出不匹配。@Jotne,我认为我不能使用此sed,因为我们不知道将获得什么特殊字符。例如,我们也从别处得到了|我不认为我可以使用这个sed,因为我们不知道我们将得到什么样的特殊角色。例如,我们也不知从何而来。您能建议对u进行任何更改吗?我将保留-、|、u,并用u替换任何其他字符。@SanthoshRam第一次替换将删除除您选择的字符以外的所有字符,即
    a
    z
    a
    z
    0
    9
    *
    =
    /
    -
    将保留,其他所有内容将被删除。我认为我不能使用此sed,因为我们不知道将获得什么特殊字符。例如,我们也不知从何而来。您是否可以建议对uuz>进行任何更改以适应uuuz?@Santosh使用否定字符类的目的是您不需要知道将获得什么“特殊”字符,因为所有非字母数字或
    -
    的字符都将被视为“特殊”。为什么不试试这个脚本,看看它是否有效,而不是假设它不会有效呢?它确实有效。多谢。。有一件事我注意到了,一个用双引号引起来的字符串被转换成
    \u字符串
    ,这让我有点担心。有没有办法修复它?在你的样本输入/输出中包含那个例子来告诉我们应该如何处理它,但是我怀疑你只需要添加<代码> <代码>(和其他你不认为是特殊的字符)。
    sed -E 's/[^[:alnum:]|_.,*=/-]//g;s/[*=/]+/_/g;s/--+|__+/_/g' file
    
      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
    
    sed -r -e 's#([^a-zA-Z0-9\|_])+#_#g' -e 's/_+/_/g'