我试图在这里找到一些我可以使用的先前问题,但不幸的是找不到我的确切案例。
我想从另一个命令的输出中获取如下所示的内容:
pattern.d
17.91
17.55
pattern.b
pattern.a
7.21
9.34
pattern.c
对此:
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000
我尝试多解释一下:在包含字符串“pattern”的每一行之后应该始终有一个数字。如果没有,我想插入一个值为 1000 的新行。
请注意,模式有一个变化的“扩展名”(.a .b .c .d 但不是“扩展名”中的数字),它将帮助我稍后按字母顺序对内容进行排序。
编辑:我已经接受了一个答案,但如果有人仍然想寻找另一种变体,我应该指定“模式”的出现有所不同,并且可能有超过 2 或 3 个连续的,例如:
pattern.a
pattern.d
pattern.c
pattern.d
pattern.b
17.91
答案1
这是一个sed
适用于任何输入的解决方案(例如匹配的多个连续行pattern
):
sed '1{ # when on first line
x # exchange
s/^/1000/ # replace the empty hold buffer with "1000"
x # exchange back
}
: do # label "do"
/pattern/{ # if the current line matches "pattern"
${ # if we're on the last line
G # append hold buffer content to pattern space
b # go to end of script
}
n # otherwise print and pull in the next line
/^[[:digit:]]/!{ # if this one doesn't start with a digit
x # exchange
p # print (the pattern space is now "1000")
x # exchange back
b do # go to label "do"
}
}' infile
有了gnu sed
它就可以写成
sed '1{x;s/^/1000/;x};:b;/pattern/{${G;b};n;/^[[:digit:]]/!{x;p;x;bb}}' infile
您可以执行类似的操作awk
:
awk -vc=0 '!/^[[:digit:]]/{
if (c) {print "1000"}
}
{ if (/pattern/){c=1} else{c=0}
}
END{if (c){print "1000"}
};1' infile
也就是说,c=1
在匹配的行上设置pattern
,c=0
在其余行上设置,在不以数字开头的每一行上设置(以及在块中END
)检查是否c
已设置(或1
- 意味着上一行匹配pattern
) - 如果是打印1000
。
答案2
sed -e '
$!{
/pattern\.[a-z]/N
/\n/!b
/\n[+-]\{0,1\}[.][0-9]\{1,\}$/b
/\n[+-]\{0,1\}[0-9]\{1,\}\([.][0-9]*\)\{0,1\}$/b
h;s/\(.*\n\).*/\11000/p
g;D
}
/pattern\.[a-z]/a\
1000
' yourfile
结果
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000
在职的
- 虽然不在 eof 处,但
$!{...}
我们将下一行附加到模式空间,条件是当前行是感兴趣的行。 - 然后,我们在以下情况下跳过任何进一步的处理:a) 未找到换行符 => 当前行中没有模式。 b) 第二行中的 .nnn 格式的浮点数。 c) 格式为 mmm、mmm. 或 mmm.nnn 的浮点数仅出现在第二行。 d) 排除任何可能性 => 我们需要将幻数 1000 添加到换行符之后的下一行末尾。
答案3
如果 的连续实例绝不会超过两个pattern
,并且您有 GNU sed,那么:
sed '/^pattern/ {$!N; /\n[0-9]/b; s/$/\n1000/M}' file
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000
怎么运行的:
- 如果当前行以
pattern
then 开头- 如果我们不在 EOF,请附加下一行
- 如果换行符后面有一个数字(可以更具体),则
b
退出(即继续到下一行);别的 - 替换以换行符结尾的第一行并
1000
GNU 特定的M
修饰符允许$
匹配 or \n
,$
以便它处理“正常”情况和 EOF 情况(不附加后续行)。
答案4
awk解决方案:
awk '{ if ($0 ~ /pattern/) { # if it's a `pattern` line
if ((getline nl) > 0) { # check if next record exists
# if next record hasn't number - insert `1000`, otherwise - print current and next records as they are
print ((nl !~ /^[0-9]/)? $0 ORS 1000 ORS nl: $0 ORS nl)
} else {
print $0 ORS 1000 # if the file ends up with pattern - insert `1000`
}
} else {
print $0 # print other record
}
}' file
输出:
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000