如何 sed -e 's///' 除特定模式之外的所有内容?

如何 sed -e 's///' 除特定模式之外的所有内容?

如何用 sed 替换字符串中的所有内容(除了 % 和直接紧随其后的任何数字)?意思是,除了字符串之外的所有内容,例如:

%1 %1000 %55 ETC。

给定这种形式的字符串:

    1: [18x14] [history 1/2000, 268 bytes] %3
    2: [18x14] [history 1/2000, 268 bytes] %4 (active)

我只想得到%3%4零件。数字最多可达999.

答案1

$ sed 's/^.*\(%[0-9]\+\).*$/\1/' input

假设一行至多包含一个这些%123标记,并且每一行都包含这样一个标记。

\( \)字符标记一个匹配组 - 然后通过\1反向引用在替换中引用该匹配组。^/$匹配行的开头/结尾。

否则,您可以预先过滤输入,例如:

$ grep '%[0-9]\+' input | sed 's/^.*\(%[0-9]\+\).*$/\1/'

(当并非所有行都包含这样的标记时)

另一种变体:

$ sed 's/\(%[0-9]\+\)/\n\1\n/g' | grep '%[0-9]'

(当一行可能包含多个这些标记时)

以下是直接在每个标记之前和之后插入的换行符 - 在管道的第一部分中。然后该grep部分删除所有非%123标记行。

答案2

grep -o在这种情况下你最好使用:

grep -oP '\B%[0-9]{1,3}\b' inputfile

假设您的版本grep支持 Perl 兼容的正则表达式 ( -P)。否则:

grep -o '\B%[0-9]\{1,3\}\b' inputfile

使用 GNU sed,可以将空格音译为换行符并获得所需的行:

sed 'y/ /\n/' inputfile | sed '/^%[0-9]\{1,\}/!d'

答案3

使用时sed几乎总是建议:

/address then/s/earch/replace/

有两个原因。第一个是多行/addressing/更快 - 它仅针对寻找匹配,并且不必只选择行的一部分进行编辑,因此可以更快地缩小结果范围。

第二个原因是您可以对同一地址执行多个编辑操作 - 这使事情变得更加容易。

当然,在这种情况下,仅给出您显示的数据,这没有实际区别。不过,这就是我会做你问的事情的方式:

sed '/^[^%]*\|[^0-9]*$/s///g' <<\DATA
    1: [18x14] [history 1/2000, 268 bytes] %3
    2: [18x14] [history 1/2000, 268 bytes] %4 (active)
DATA

#OUTPUT
%3
%4

它只是选择所有字符非-%从行首开始的字符以及所有字符非数字的地址中行尾的字符,然后用s///- 删除它们,就是这样。

在当前的形式下,如果您向其提供行,它可能会以意想不到的方式破坏数据不是包含一个%digit组合 - 这就是为什么寻址很重要。如果我们稍微改变一下:

/%[0-9]/s/[^%]*\|[^0-9]*$//g

变得更安全快点。

答案4

我的解决方案不使用 sed,而是使用带有扩展正则表达式和仅匹配选项的 grep。


$ cat file
1: [18x14] [history 1/2000, 268 bytes] %3
2: [18x14] [history 1/2000, 268 bytes] %4 (active)
$ cat file | grep -Eo '%[0-9]+'
%3
%4

在这种情况下使用 grep 比使用 sed 更简单。

相关内容