Linux 如何在两个特殊字符之间使用sed或grep并修改输出

Linux 如何在两个特殊字符之间使用sed或grep并修改输出,linux,shell,unix,sed,sh,Linux,Shell,Unix,Sed,Sh,我想在这两者之间做任何事!然后呢? 比如说 !喂,我叫X? X是介于0-9之间的数字 并将其输出到 Xhello my name isX 我当然想在文本文件中获得所有这些模式,然后删除任何其他内容 例如: blabla foo bar !3 whats up 3? !4 hello im new to this forum 4? foo bar now 结果: 3whats up3 4hello im new to this forum4 也许有人可以帮助我,我只想使用sh和this命令假

我想在这两者之间做任何事!然后呢? 比如说

!喂,我叫X?

X是介于0-9之间的数字
并将其输出到

Xhello my name isX
我当然想在文本文件中获得所有这些模式,然后删除任何其他内容

例如:

blabla
foo bar !3 whats up 3?
!4 hello im new
to this forum 4?
foo bar now
结果:

3whats up3
4hello im new to this forum4

也许有人可以帮助我,我只想使用sh和this命令

假设我们有一个包含内容的输入文件(故意将其复杂化以涵盖扩展情况):


两种方法:

3whats up3
4hello im new to this forum4
--awk进近:

awk -v RS='!' 'match($0,/^([0-9]) ([^!?]*) ([0-9])?/,a){ gsub(/\n/,"",a[2]); print a[1]a[2]a[3] }' file
  • -vrs='!'-正在考虑
    作为记录分隔符

  • 匹配($0,/^([0-9])([^!?]*)([0-9])?/,a)
    -匹配所需序列并将捕获的组
    (…)
    值放入数组
    a


--粘贴+grep+sed管道:

paste -d' ' -s file | grep -o '![0-9] [^!?]* [0-9]?' | sed -En 's/!([0-9]+) (.*) ([0-9]+)\?/\1\2\3/p'
  • 粘贴-d'-s文件
    -使用空格作为分隔符合并文件行

  • grep-o'![0-9][^!?]*[0-9]?'
    -只搜索和输出与模式匹配的所需序列

  • sed-En's/!([0-9]+)(.*)([0-9]+)\?/\1\2\3/p'
    -在捕获的组下执行替换


输出(对于两种方法):


假设我们有一个包含内容的输入文件(有意将其复杂化以涵盖扩展情况):


两种方法:

3whats up3
4hello im new to this forum4
--awk进近:

awk -v RS='!' 'match($0,/^([0-9]) ([^!?]*) ([0-9])?/,a){ gsub(/\n/,"",a[2]); print a[1]a[2]a[3] }' file
  • -vrs='!'-正在考虑
    作为记录分隔符

  • 匹配($0,/^([0-9])([^!?]*)([0-9])?/,a)
    -匹配所需序列并将捕获的组
    (…)
    值放入数组
    a


--粘贴+grep+sed管道:

paste -d' ' -s file | grep -o '![0-9] [^!?]* [0-9]?' | sed -En 's/!([0-9]+) (.*) ([0-9]+)\?/\1\2\3/p'
  • 粘贴-d'-s文件
    -使用空格作为分隔符合并文件行

  • grep-o'![0-9][^!?]*[0-9]?'
    -只搜索和输出与模式匹配的所需序列

  • sed-En's/!([0-9]+)(.*)([0-9]+)\?/\1\2\3/p'
    -在捕获的组下执行替换


输出(对于两种方法):


一个单独的
awk
命令,虽然不是很简单,但效率很高:

awk '
  {
    from = match($0, "![0-9] ")
    if (from) {
      $0 = substr($0, from+1, RLENGTH-2) substr($0, from + RLENGTH)
    }
    to = match($0, " [0-9]\\?")
    if (to) {
      $0 = substr($0, 1, to-1) substr($0, to+1, length($0)-to-1)
    }
    if (from && to)  print
    else if (from)   printf "%s ", $0
    else if (to)     print
  }
' file

注:假设没有
序列跨越两行以上(要使解决方案适应这种情况并不困难)。

一个单独的
awk
命令,虽然不简单,但效率很高:

awk '
  {
    from = match($0, "![0-9] ")
    if (from) {
      $0 = substr($0, from+1, RLENGTH-2) substr($0, from + RLENGTH)
    }
    to = match($0, " [0-9]\\?")
    if (to) {
      $0 = substr($0, 1, to-1) substr($0, to+1, length($0)-to-1)
    }
    if (from && to)  print
    else if (from)   printf "%s ", $0
    else if (to)     print
  }
' file
注:假设没有
序列跨越2行以上(要使解决方案适应这种情况并不困难)。

使用GNU awk:

$ cat file2
blabla
foo bar !3 whats up 3?
!4 hello im new
to this forum 4?
foo bar 2345 now

$ awk -v RS="[!?]" '{gsub("\n"," ")}$0 ~ /^[0-9].*[0-9]$/{sub(" ","");print gensub(/ ([0-9]$)/,"\\1","g")}' file2
3whats up3
4hello im new to this forum4
使用GNU awk:

$ cat file2
blabla
foo bar !3 whats up 3?
!4 hello im new
to this forum 4?
foo bar 2345 now

$ awk -v RS="[!?]" '{gsub("\n"," ")}$0 ~ /^[0-9].*[0-9]$/{sub(" ","");print gensub(/ ([0-9]$)/,"\\1","g")}' file2
3whats up3
4hello im new to this forum4
这可能适合您(GNU sed&tr):

或:

或作为一个:

sed -nr '/\n/ba;H;$!d;x;y/\n!?/ \n\n/;s/^([0-9])\s*|\s*([0-9])$/\1\2/Mg;:a;/^([0-9])[^\n]*\1\n/P;D' file
这可能适合您(GNU sed&tr):

或:

或作为一个:

sed -nr '/\n/ba;H;$!d;x;y/\n!?/ \n\n/;s/^([0-9])\s*|\s*([0-9])$/\1\2/Mg;:a;/^([0-9])[^\n]*\1\n/P;D' file

随便什么!还有如果有一行代码呢!你好,我是新来的!1为什么?2?
?应该如何治疗?假设如此!然后呢?永远不会被用于任何事情之间!还有如果有一行代码呢!你好,我是新来的!1为什么?2?
?应该如何治疗?假设如此!然后呢?永远不会被使用