コードを複製せずに特定のパターンをフィルタリングして印刷する方法はありますか?

コードを複製せずに特定のパターンをフィルタリングして印刷する方法はありますか?

ソフトウェアをインストールすると、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

ただし、これには同じ内容を2回入力する必要があります。正規表現を繰り返さずに同じことを行う方法はありますか?

答え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'

関連情報