有没有一种方法可以过滤并打印特定模式而不重复代码?

有没有一种方法可以过滤并打印特定模式而不重复代码?

如果我用来pacman安装软件,我偶尔会遇到以下形式的错误

package-name: /some/package/file exists in filesystem

如果我过去某个时候搞砸了安装,不明智地尝试手动安装某些东西等等,通常会发生这种情况。

为了解决这个问题,将所有冲突的包的名称放在一个文件中是很有用的。我可以使用以下方法来做到这一点

# pacman -S package-name |
   grep '^package-name: [^ ]* exists in filesystem$' |
   sed 's/^package-name: \([^ ]*\) exists in filesystem$/\1/' >
   conflicting_files.txt

然而,这需要我输入相同的内容两次。有没有办法在不重复正则表达式的情况下做同样的事情?

答案1

很多方法。例如,sed单独使用(我假设这里使用 GNU 工具,因为你正在使用pacman):

pacman -S package-name |
   sed -En 's/^package-name: ([^ ]*) exists in filesystem$/\1/p' >
   conflicting_files.txt

或者grep

pacman -S package-name |
   grep -oP '^package-name: \K\S+' >
   conflicting_files.txt

如果您需要匹配行尾,请使用@RomanPerekhrest建议

或者perl

pacman -S package-name |
   perl -ne 's/^package-name: (\S*) exists in filesystem$/$1/ && print' >
   conflicting_files.txt

或者perl

pacman -S package-name |
    perl -lane 'print $F[1] if /^package-name:.*exists in filesystem$/' >
    conflicting_files.txt

或者awk

pacman -S package-name |
    awk '/^package-name:.*exists in filesystem$/{print $2}' > 
    conflicting_files.txt

答案2

使用 GNU,grep您可以将管道缩短为以下内容:

pacman -S package-name | grep -Po '^package-name: \K[^[:space:]]+(?= exists in filesystem$)' > conflicting_files.txt

或者,您也可以更改[^[:space:]]\S以匹配非空白顺序。

答案3

只是抛出另一个选项:

packman -S package-name |
  pcregrep -xo1 'package-name: (\S+) exists in filesystem'

如同:

packman -S package-name |
  perl -lne 'print $1 if /^package-name: (\S+) exists in filesystem$/'

可移植/POSIX 方式是:

sed -n 's/^package-name: \([^ ]*\) exists in filesystem$/\1/p'

相关内容