sed 删除包含特定字符的确切数量的行

sed 删除包含特定字符的确切数量的行

我想删除恰好包含的行一个字符的实例。在本例中,字符/.

我更喜欢使用程序sed

答案1

如果必须使用sed,则命令为:

sed -E -- '\-^([^/]*/[^/]*){3}$-d'

但如果您不需要使用sed,最简单的解决方案是使用grep.

将此命令中的 N 替换为您想要的值:

egrep -vx '([^/]*/[^/]*){N}'

grep有一个-v命令行选项,可以grep显示所有执行此操作的行不是匹配正则表达式。因此,接下来的任务就是创建一个正则表达式,该表达式与恰好包含 N 次斜杠字符的行相匹配,然后grep -v与该正则表达式一起使用。

一个例子是以下模式:

[^/]*/[^/]*

N 个实例是模式:

([^/]*/[^/]*){N}

恰好 N 个实例的模式是:

^([^/]*/[^/]*){N}$

对于仅匹配整行的模式(如本例),grep还具有-x命令行选项。

因此,令 N 为 3。我们的正则表达式是否可靠地仅匹配具有 3 个实例的行/

$ cat << EOF | egrep -x '([^/]*/[^/]*){3}'
/
//
///
////
/stuff
/stuff/added
/stuff/added/
/stuff/added/to/
/stuff/added/to/each
/stuff/added/to/each/line
more/stuff
more/stuff/added
more/stuff/added/
more/stuff/added/to/
more/stuff/added/to/each
more/stuff/added/to/each/line
consecutive//slashes/
/consecutive//slashes/
/consecutive//slashes
///all in one place
all in one place///
all in ///one place
EOF
///
/stuff/added/
more/stuff/added/
consecutive//slashes/
/consecutive//slashes
///all in one place
all in one place///
all in ///one place

是的,我们的正则表达式确实匹配了正确的行。现在我们只需将-v标志添加到过滤掉匹配的行并显示不匹配的行。

$ cat << EOF | egrep -vx '([^/]*/[^/]*){3}'
/
//
///
////
/stuff
/stuff/added
/stuff/added/
/stuff/added/to/
/stuff/added/to/each
/stuff/added/to/each/line
more/stuff
more/stuff/added
more/stuff/added/
more/stuff/added/to/
more/stuff/added/to/each
more/stuff/added/to/each/line
consecutive//slashes/
/consecutive//slashes/
/consecutive//slashes
///all in one place
all in one place///
all in ///one place
EOF
/
//
////
/stuff
/stuff/added
/stuff/added/to/
/stuff/added/to/each
/stuff/added/to/each/line
more/stuff
more/stuff/added
more/stuff/added/to/
more/stuff/added/to/each
more/stuff/added/to/each/line
/consecutive//slashes/

答案2

您还可以使用 awk: 指定/为字段分隔符,并查找n+1字段。

awk -F'/' -v n=3 'NF != n + 1' file

答案3

您可以使用此 pbm。如下:

$ perl -ne 'tr|/|/| == 3 || print' inp

这里我们依靠 Perl 函数的属性tr来返回它对输入字符串(在本例中为当前记录)所做的翻译次数。因此,当输入记录中恰好有三个斜杠时,我们不会打印该记录,但在所有其他情况下我们都会打印该记录。

这次使用的另一种方法POSIX sed可以是:

$ sed -e 's:/:/:4;t' -e 's//\n/3' -e '/\n/d' inp

在这里,我们首先测试是否有超过 3 个斜杠,如果是,我们使用模式空间分支到 sed 代码的末尾。 OTW,模式空间中将出现 3 个或更少的斜杠。现在我们测试第三个斜杠是否可以\n在模式空间中被换行符 , 替换。如果在这个替换之后我们看到一个换行符=>输入中正好有三个斜杠。因为我们不想看到正好 3 个斜杠,所以我们删除了这个模式空间。 OTW,剩下的任何内容(=> 具有 2 个或更少斜杠的模式空间)都会被带到标准输出。

注意:\n在最后一种情况下无法找到,因为s//\n/3替换不成功。

另一种使用方法POSIX sed是:

$ sed -e h -e 's|[^/]||g' -e '/^.\{3\}$/d' -e g inp

存储当前记录的副本并删除所有非斜杠。现在检查模式空间中是否正好有三个字符(实际上现在它们都是斜杠)。如果是,我们会立即删除它。 OTW,从保留中调用存储的记录,然后 sed 默认为您打印它。

HTH。

答案4

一种方法可能是:

  • 尝试更换(替代)(N+1)该字符第 次出现;如果替换成功,则开始新的循环(分支出)

  • 尝试更换(替代)该字符第 次出现;如果替换失败,则开始新的循环(分支出)

(别的)

  • 删除该行

使用 GNU sed,并采取N = 2:

$ printf 'foo/\nfoo/bar/\nfoo/bar/baz/\n' | sed -e 's,/,/,3;t' -e 's,/,/,2;T' -ed
foo/
foo/bar/baz/

相关内容