Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.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
Regex 仅当条件适用时,才在bash中删除非ascii字符_Regex_Bash_Awk_Sed_Hex - Fatal编程技术网

Regex 仅当条件适用时,才在bash中删除非ascii字符

Regex 仅当条件适用时,才在bash中删除非ascii字符,regex,bash,awk,sed,hex,Regex,Bash,Awk,Sed,Hex,我有一个非常具体的需求,我一直在努力解决,但没有成功 我有一个日志,它是由tcp/ip套接字转储创建的。。。它将十六进制转换为ASCII,但其中自然有一些特殊字符 我已经设法删除了它们,但我目前遇到了一个困难:有时会发送0x0A,这会干扰我的应用程序。。。我试图删除它,但它同时也删除了行末尾的有效0x0A 基本上,我在日志文件中: 08-14-2017 10:00:00 String={Teste String} 08-14-2017 10:00:00 String={ Teste String

我有一个非常具体的需求,我一直在努力解决,但没有成功

我有一个日志,它是由tcp/ip套接字转储创建的。。。它将十六进制转换为ASCII,但其中自然有一些特殊字符

我已经设法删除了它们,但我目前遇到了一个困难:有时会发送0x0A,这会干扰我的应用程序。。。我试图删除它,但它同时也删除了行末尾的有效0x0A

基本上,我在日志文件中:

08-14-2017 10:00:00 String={Teste String}
08-14-2017 10:00:00 String={
Teste String2}
08-14-2017 10:00:00 String={
Teste String3}
08-14-2017 10:00:00 String={Teste String4}
我想要最后的结果

08-14-2017 10:00:00 String={Teste String}
08-14-2017 10:00:00 String={Teste String2}
08-14-2017 10:00:00 String={Teste String3}
08-14-2017 10:00:00 String={Teste String4}
字符始终在{}之间,因此}之后的每个0x0A都有效,但内部无效

我尝试的每个命令要么删除所有0x0A,要么根本不起作用

我试过这样的方法

sed 's/^[^}]*}//'
sed 's/\x0A$//'

有什么想法吗

这在sed中当然是可能的,但在awk中更容易阅读和理解:

awk 'BEGIN{ OFS=FS="{"; ORS=RS="}" } { sub(/[^[:print:]]/,"",$2) } 1' input.txt
这有什么用?

  • 首先,我们将输入和输出字段分隔符设置为
    {
    ,将输入和输出记录分隔符设置为
    }
    。这让我们可以预测地将括号内的文本作为一个特定字段(至少基于您的示例数据)
  • 接下来,我们用空字符串替换字段#2中的任何不可打印字符,从而消除换行符、退格等
  • 最后,我们使用awk速记打印该行

    • 这当然可以通过sed实现,但在awk中更容易阅读和理解:

      awk 'BEGIN{ OFS=FS="{"; ORS=RS="}" } { sub(/[^[:print:]]/,"",$2) } 1' input.txt
      
      这有什么用?

      • 首先,我们将输入和输出字段分隔符设置为
        {
        ,将输入和输出记录分隔符设置为
        }
        。这让我们可以预测地将括号内的文本作为一个特定字段(至少基于您的示例数据)
      • 接下来,我们用空字符串替换字段#2中的任何不可打印字符,从而消除换行符、退格等
      • 最后,我们使用awk速记打印该行

        • 带sed的

          Linux:

          $ sed -r ':a;N;$!ba;s/(\{[^}]*)\\n([^{]*\})/\1\2/g' file
          08-14-2017 10:00:00 String={Teste String}
          08-14-2017 10:00:00 String={Teste String2}
          08-14-2017 10:00:00 String={Teste String3}
          08-14-2017 10:00:00 String={Teste String4}
          
          FreeBSD和macOS:

          sed -e ':a' -e 'N;$!ba' -e 's/(\{[^}]*)\\n([^{]*\})/\1\2/g' file
          

          解释

          -e':a'-e'N;$!BA’/代码>允许我们在SED的每次迭代中同时考虑当前和下一行。有关详细信息,请参阅

          (\{[^}]*)
          确保左大括号后面没有右大括号


          ([^{]*\})
          的作用正好相反。

          使用sed

          Linux:

          $ sed -r ':a;N;$!ba;s/(\{[^}]*)\\n([^{]*\})/\1\2/g' file
          08-14-2017 10:00:00 String={Teste String}
          08-14-2017 10:00:00 String={Teste String2}
          08-14-2017 10:00:00 String={Teste String3}
          08-14-2017 10:00:00 String={Teste String4}
          
          FreeBSD和macOS:

          sed -e ':a' -e 'N;$!ba' -e 's/(\{[^}]*)\\n([^{]*\})/\1\2/g' file
          

          解释

          -e':a'-e'N;$!BA’/代码>允许我们在SED的每次迭代中同时考虑当前和下一行。有关详细信息,请参阅

          (\{[^}]*)
          确保左大括号后面没有右大括号

          ([^{]*\})
          的作用正好相反。

          Perl:

          $ perl -0777 -pe 's/({[^}]*)\x0A([^}]*})/\1\2/g' file
          08-14-2017 10:00:00 String={Teste String}
          08-14-2017 10:00:00 String={Teste String2}
          08-14-2017 10:00:00 String={Teste String3}
          08-14-2017 10:00:00 String={Teste String4}
          
          纯Bash(基于anubhava的awk):

          而IFS=“\n”读取-r行;做
          le=“”
          [[$line=~\}]&&le=$'\n'
          printf“%s%s”$line“$le”
          完成Perl:

          纯Bash(基于anubhava的awk):

          而IFS=“\n”读取-r行;做
          le=“”
          [[$line=~\}]&&le=$'\n'
          printf“%s%s”$line“$le”
          完成另一个更简单的
          awk

          awk '{printf "%s%s", $0, (/}/ ? ORS : "")}' file
          
          08-14-2017 10:00:00 String={Teste String}
          08-14-2017 10:00:00 String={Teste String2}
          08-14-2017 10:00:00 String={Teste String3}
          08-14-2017 10:00:00 String={Teste String4}
          
          awk
          命令检查一行中是否存在
          }
          ,然后只打印换行符,否则将打印不带换行符的记录。

          另一个更简单的
          awk

          awk '{printf "%s%s", $0, (/}/ ? ORS : "")}' file
          
          08-14-2017 10:00:00 String={Teste String}
          08-14-2017 10:00:00 String={Teste String2}
          08-14-2017 10:00:00 String={Teste String3}
          08-14-2017 10:00:00 String={Teste String4}
          

          awk
          命令检查一行中是否存在
          }
          ,然后只打印换行符,否则将打印不带换行符的记录。

          对于多字符,使用GNU awk,我们只需隔离每个
          {…}
          字符串并删除其中的换行符即可:

          $ awk -v RS='{[^}]+}' '{ORS=gensub(/\n/,"","g",RT)}1' file
          08-14-2017 10:00:00 String={Teste String}
          08-14-2017 10:00:00 String={Teste String2}
          08-14-2017 10:00:00 String={Teste String3}
          08-14-2017 10:00:00 String={Teste String4}
          

          对于这种特定的情况,其他awk答案将很好地工作,以上只是隔离分隔字符串的问题的一个更一般的解决方案,然后对其执行操作,就像在这种情况下删除字符一样。

          对于多字符的GNU awk,我们可以只隔离每个
          {…}
          字符串并删除其中的换行符:

          $ awk -v RS='{[^}]+}' '{ORS=gensub(/\n/,"","g",RT)}1' file
          08-14-2017 10:00:00 String={Teste String}
          08-14-2017 10:00:00 String={Teste String2}
          08-14-2017 10:00:00 String={Teste String3}
          08-14-2017 10:00:00 String={Teste String4}
          

          对于这种特殊情况,其他awk答案也可以,以上只是隔离分隔字符串,然后对其执行操作(如本例中删除字符)问题的更一般解决方案。

          您是在ASCII文本上应用sed命令还是在十六进制上应用sed命令?在ASCII文本上……您是在ASCII文本上应用sed命令还是在十六进制上应用sed命令?在ASCII文本上……不是吗在FreeBSD或macOS中为我工作。这是GNU sed特有的吗?当您将其拆分时,它会起作用:
          sed-E-E':a'-E'N;$!ba'-e's/(\{[^}]*)\n([^{]*\})/\1\2/g'
          。。非GNU sed似乎希望标签后面不要跟分号。@ghoti谢谢。我更新了。这应该适用于GNU-sed和非GNU-sed(?)。
          \n
          不能跨sed版本移植(您需要反斜杠后跟文字换行符以便于移植),
          -E
          只能在GNU和OSX-sed中工作,而
          -r
          只能在GNU-sed中工作。此外,Solaris 10中的sed不支持
          -E
          -r
          ,因此最好使用基于BRE的解决方案以实现最大的可移植性。在bash中,您可以使用格式替换获得嵌入的文字换行符,即
          $'foo\nbar'
          。在FreeBSD或macOS中不适用于我。这是GNU sed特有的吗?当您将其拆分时,它会起作用:
          sed-E-E':a'-E'N;$!ba'-e's/(\{[^}]*)\n([^{]*\})/\1\2/g'
          。。非GNU sed似乎希望标签后面不要跟分号。@ghoti谢谢。我更新了。这应该适用于GNU-sed和非GNU-sed(?)。
          \n
          不能跨sed版本移植(您需要反斜杠后跟文字换行符以便于移植),
          -E
          只能在GNU和OSX-sed中工作,而
          -r
          只能在GNU-sed中工作。此外,Solaris 10中的sed不支持
          -E
          -r
          ,因此最好使用基于BRE的解决方案以实现最大的可移植性。在bash中,可以获得嵌入的文本newli