Shell 记住前一行中的匹配项,仅在连续行包含与sed匹配项时打印一次

Shell 记住前一行中的匹配项,仅在连续行包含与sed匹配项时打印一次,shell,awk,sed,Shell,Awk,Sed,警方通缉: 我想知道如何在一行中保存/记住匹配项,如标题部分,而不立即打印它 如果在下一行的某个地方发现了其他匹配项,则将其打印出来 但是,对于该标题下的任何数量的以下其他匹配,保存/记住的标题部分只应打印一次 而且,如果在记住的标题行下面的任何一行中没有其他内容的匹配项,则根本不应该打印它 例如,对于ifconfig 但是我只想为它的所有IP获取一次标题,这样就不会造成混乱 lo0: inet 127.0.0.1 inet 127.94.0.2 inet 127.94.

警方通缉:

我想知道如何在一行中保存/记住匹配项,如标题部分,而不立即打印它

如果在下一行的某个地方发现了其他匹配项,则将其打印出来

但是,对于该标题下的任何数量的以下其他匹配,保存/记住的标题部分只应打印一次

而且,如果在记住的标题行下面的任何一行中没有其他内容的匹配项,则根本不应该打印它

例如,对于ifconfig

但是我只想为它的所有IP获取一次标题,这样就不会造成混乱

lo0:
    inet 127.0.0.1
    inet 127.94.0.2
    inet 127.94.0.1
en3:
    inet 192.168.0.2

所以我在昨晚想出了怎么做:

ifconfig | gsed -n -E '
/^[a-z0-9]*:/ {                     # for lines starting with this
    s/^([a-z0-9]*:).*/\1/;h         # extract the start and put it into hold space
}
/\tinet (addr:)?[0-9.a-fA-F:]*/ {   # for lines containing this
    s/^.*(\tinet (addr:)?[0-9.a-fA-F:]*).*/\1/    # extract it
    x                               # swap hold space and pattern space
    G                               # and then append the hold space (former pattern space) to it 
    s/^\n//                         # replace leading \n if former hold space was empty
    p                               # print the concatenated former hold space and modified pattern space
    s/^.*$//                        # empty the pattern space
    x                               # swap the now empty pattern space to hold space
}
'
或作为多个或少个一行:

ifconfig | gsed -n -E '
/^[a-z0-9]*:/                   { s/^([a-z0-9]*:).*/\1/;h };
/\tinet (addr:)?[0-9.a-fA-F:]*/ { s/^.*(\tinet (addr:)?[0-9.a-fA-F:]*).*/\1/;x;G;s/^\n//;p;s/^.*$//;x}'
给了我想要的东西

lo0:
    inet 127.0.0.1
    inet 127.94.0.2
    inet 127.94.0.1
en3:
    inet 192.168.0.2

所以我在昨晚想出了怎么做:

ifconfig | gsed -n -E '
/^[a-z0-9]*:/ {                     # for lines starting with this
    s/^([a-z0-9]*:).*/\1/;h         # extract the start and put it into hold space
}
/\tinet (addr:)?[0-9.a-fA-F:]*/ {   # for lines containing this
    s/^.*(\tinet (addr:)?[0-9.a-fA-F:]*).*/\1/    # extract it
    x                               # swap hold space and pattern space
    G                               # and then append the hold space (former pattern space) to it 
    s/^\n//                         # replace leading \n if former hold space was empty
    p                               # print the concatenated former hold space and modified pattern space
    s/^.*$//                        # empty the pattern space
    x                               # swap the now empty pattern space to hold space
}
'
或作为多个或少个一行:

ifconfig | gsed -n -E '
/^[a-z0-9]*:/                   { s/^([a-z0-9]*:).*/\1/;h };
/\tinet (addr:)?[0-9.a-fA-F:]*/ { s/^.*(\tinet (addr:)?[0-9.a-fA-F:]*).*/\1/;x;G;s/^\n//;p;s/^.*$//;x}'
给了我想要的东西

lo0:
    inet 127.0.0.1
    inet 127.94.0.2
    inet 127.94.0.1
en3:
    inet 192.168.0.2

你能试一下吗

Your_command | awk '
/^[a-zA-Z]+/{
  count=""
  val=$1
  next
}
val && match($0,/.*[0-9]+\.[-0-9]+\.[0-9]+\.[0-9]+ +/){
  if(++count==1){
    print val
  }
  value=substr($0,RSTART,RLENGTH)
  sub(/ +$/,"",value)
  print value
  value=""
}
' 

你能试一下吗

Your_command | awk '
/^[a-zA-Z]+/{
  count=""
  val=$1
  next
}
val && match($0,/.*[0-9]+\.[-0-9]+\.[0-9]+\.[0-9]+ +/){
  if(++count==1){
    print val
  }
  value=substr($0,RSTART,RLENGTH)
  sub(/ +$/,"",value)
  print value
  value=""
}
' 

我有两个建议:

清理输入行时,有时更容易删除而不是选择。 在这种情况下,更容易在保持空间中收集最终输出。 例如:

解析

按如下方式运行:

ifconfig | gsed -nEf parse.sed
输出:

lo0: inet 127.0.0.1 inet 127.94.0.2 inet 127.94.0.1 en3: inet 192.168.0.2
我有两个建议:

清理输入行时,有时更容易删除而不是选择。 在这种情况下,更容易在保持空间中收集最终输出。 例如:

解析

按如下方式运行:

ifconfig | gsed -nEf parse.sed
输出:

lo0: inet 127.0.0.1 inet 127.94.0.2 inet 127.94.0.1 en3: inet 192.168.0.2 sed用于简单的s/old/new,也就是说,对于其他任何东西,只需使用awk:

$ ifconfig | awk '/^[[:alpha:]]/{hdr=$1 ORS} $1=="inet"{print hdr "    " $1, $2; hdr=""}'
lo0:
    inet 127.0.0.1
    inet 127.94.0.2
    inet 127.94.0.1
en3:
    inet 192.168.0.2
sed用于简单的s/old/new,也就是说,对于其他任何东西,只需使用awk:

$ ifconfig | awk '/^[[:alpha:]]/{hdr=$1 ORS} $1=="inet"{print hdr "    " $1, $2; hdr=""}'
lo0:
    inet 127.0.0.1
    inet 127.94.0.2
    inet 127.94.0.1
en3:
    inet 192.168.0.2

这可能适用于GNU sed:

sed -En '/^\S/h;s/^(\s+inet\s+\S+).*/\1/;T;x;s/\s.*//p;x;p' file
将标题行存储在保留空间中

删除包含inet的行的ip地址后的任何内容

如果替换不成功,则进行纾困。否则,请返回保留空间并尝试删除标题行的结尾并打印它

返回模式空间并打印原始ip地址行


注意:页眉只打印一次,因为一旦行被编辑,替换将失败。

这可能适用于GNU-sed:

sed -En '/^\S/h;s/^(\s+inet\s+\S+).*/\1/;T;x;s/\s.*//p;x;p' file
将标题行存储在保留空间中

删除包含inet的行的ip地址后的任何内容

如果替换不成功,则进行纾困。否则,请返回保留空间并尝试删除标题行的结尾并打印它

返回模式空间并打印原始ip地址行


注意:标题只打印一次,因为一旦行被编辑,替换将失败。

不要解析ifconfig输出,它是旧的。移动到ip a。不要解析ifconfig输出,它是旧的。转到ip a。