![如何通过一次 sed 调用仅打印第 n 个替换?](https://linux22.com/image/188239/%E5%A6%82%E4%BD%95%E9%80%9A%E8%BF%87%E4%B8%80%E6%AC%A1%20sed%20%E8%B0%83%E7%94%A8%E4%BB%85%E6%89%93%E5%8D%B0%E7%AC%AC%20n%20%E4%B8%AA%E6%9B%BF%E6%8D%A2%EF%BC%9F.png)
我有这个,其中几乎做我想做的事
git show-branch --current 62cba3e2b3ba8e1115bceba0179fea6c569d9274 \
| sed --quiet --regexp-extended 's/^.*\* \[[a-z]+\/(B-[0-9]+)-([a-z0-9-]+)\].*/\1 \2/p' \
| sed --quiet 2p #combine this into the previous sed to avoid another pipe/fork
和输出
B-47120 java-11-take2
git show-branch
正在输出这个
! [62cba3e2b3ba8e1115bceba0179fea6c569d9274] B-48141 remove env prefix
* [ccushing/B-47120-java-10-take1] B-48141 remove env prefix
--
* [ccushing/B-47120-java-11-take2] B-48141 remove env prefix
+* [62cba3e2b3ba8e1115bceba0179fea6c569d9274] B-48141 remove env prefix
您会注意到 已sed
通过管道传输到sed
,这是因为我只想要第二行。我还没有找到将2p
和 表达式组合成单个命令的方法。我尝试过各种各样的事情。我收到这样的错误
sed: can't read 2p: No such file or directory
sed: can't read s/^.*\* \[[a-z]+\/(B-[0-9]+)-([a-z0-9-]+)\].*/\1 \2/p: No such file or directory
我在适用于 Windows 的 git,并且仅限于附带的工具。
答案1
Sed 一次将每一行读入模式空间。保留空间是一个附加槽,最初是空的,仅在明确命令时才会填充。
要仅打印第二个替换的匹配项,
sed -nE '/.*\* \[[a-z]+\/(B-[0-9]+)-([a-z0-9-]+)\].*/{s//\1\2/;x;/./{x;p;q}}'
/pattern/{ # If the line matches the pattern
s//replacement/ # Substitute the pattern by the replacement¹
x # Swap hold space and pattern space
/./{ # If the pattern space is not empty, then
x # Swap hold space and pattern space
p # Print the line
q # Quit
}
}
仅打印n第 次替换的比赛(此处n=3
),
sed -nE '/pattern/{s//replacement/;H;x;/(.*\n){3}/{s///p;q};x}'
/pattern/{ # If the line matches the pattern
s//replacement/ # Substitute the pattern by the replacement¹
H # Append a newline and the pattern space to the hold space
x # Swap hold space and pattern space
/(.*\n){3}/{ # If the pattern space contains 3 newline characters²
s///p # Delete all up to the last newline¹
q # Quit
}
x # Swap hold space and pattern space
}
1:空模式与上次使用的模式相同。 2:如果不使用该标志,
则转义括号和大括号(即)。\(.*\n\)\{3\}
-E
答案2
如果我们将 sed 表达式放在一个变量中(没有最后一个p
):
subs='s/^.*\* \[[a-z]+\/(B-[0-9]+)-([a-z0-9-]+)\].*/\1 \2/'
并且,还将git-branch
输出放入另一个变量中:
outout='! [62cba3e2b3ba8e1115bceba0179fea6c569d9274] B-48141 remove env prefix
* [ccushing/B-47120-java-11-take2] B-48141 remove env prefix
--
* [ccushing/B-47120-java-11-take2] B-48141 remove env prefix
+* [62cba3e2b3ba8e1115bceba0179fea6c569d9274] B-48141 remove env prefix'
我们可以将您的命令减少为(假设是 GNU sed):
printf '%s\n' "$outout" | sed -nE "${subs}p"
现在,更改p
to;T;2p
将执行您要求执行的操作(用于;T;2{s/-/ /2g;p}
替换破折号):
$ printf '%s\n' "$outout" | sed -nE "${subs};T;2p"
B-47120 java-11-take2
请注意,数字 2 是对输入的第二行进行寻址,而不是第二个正则表达式匹配。
如果需要计算匹配行数,则需要使用 awk 或 perl,或两次调用 sed (您已经弄清楚了)。