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