ファイルの1行をその行の一部に置き換える

ファイルの1行をその行の一部に置き換える

次のコマンドを使用して、Ubuntuボックスにインストールされているプログラムのリストを取得しました。apt list --installed

これはリストの一部です。

wdiff/xenial,now 1.2.2-1build1 amd64 [installed,automatic]
wget/xenial-updates,xenial-security,now 1.17.1-1ubuntu1.5 amd64 [installed]
whiptail/xenial,now 0.52.18-1ubuntu2 amd64 [installed]
xauth/xenial,now 1:1.0.9-1ubuntu2 amd64 [installed]
xdg-user-dirs/xenial-updates,now 0.15-2ubuntu6.16.04.1 amd64 [installed]
xfsprogs/xenial-updates,now 4.3.0+nmu1ubuntu1.1 amd64 [installed]
xkb-data/xenial,now 2.16-1ubuntu1 all [installed]

プログラム名とバージョンが必要です。たとえば、次のように
wdiff/xenial,now 1.2.2-1build1 amd64 [installed,automatic] なります。
wdiff 1.2.2-1build1

私はこのコマンドが機能するように設計しました。

apt list --installed  | sed -r 's@/@ @g' | awk '{print $1 "\t" $3}'  | sort -u

入力ファイルの行の一部を含む新しいファイルを生成するためにのみsedを使用する方法を知りたいです。

この正規表現は次のとおりです。 ^([^\/]+)\/[^\s]+\s([^\s]+)

  • 行の先頭から最初の/
  • 最初のスペースを無視
  • 最初のスペースを2番目のスペースからキャプチャ

sedを使用してキャプチャグループを逆参照し、新しい出力を設定できる必要があります。

apt list --installed | sed -r 's/^([^\/]+)\/[^\s]+\s([^\s]+)/\1 \2/'

しかし、出力が私が期待したものと一致しないようです。

wdiff   [installed,automatic]
wget/xenial-updates,xenial-security,now 1.17.1-1ubuntu1.5 amd64 [installed]
whiptail    [installed]
xauth   [installed]
xdg-user-dirs/xenial-updates,now 0.15-2ubuntu6.16.04.1 amd64 [installed]
xfsprogs/xenial-updates,now 4.3.0+nmu1ubuntu1.1 amd64 [installed]
xkb-data    [installed]

何が間違っていますか?

答え1

何が間違っていますか?間違ったグループをキャプチャして保持したい最後の一致から入力文字列の最後まで削除するのではなく、空白ではなく次の項目として削除しています。

sed -r 's/^([^\/]+)\/[^\s]+\s([^\s]+)/\1    \2/'

([^/]+)   #capture everything up to /, OK
/         #discard the /. OK
[^\s]     #discard the next non white-space group, this is the bit you actually want
\s        #discard the whitespace
([^\s]+)  #capture the next non-whitespace group
#leave anything after the last non-whitespace found

すべてのエスケープ処理が読みやすくなるため、おそらくこれを行うことになります。クリーニングするとデバッグに役立ちます

sed -E 's|([^/]*)[^ ]* +([^ ]*).*|\1 \2|' infile | column -t

([^/]*)    #capture up to the /
[^ ]* +    #discard until the space and any spaces
([^ ])     #capture the next character group until a space
.*         #discard to the end of the string

グローバルマッチング()を指定しない限り、アンカーはs///g必要ありません。^

|一致文字列内の不要なエスケープを避けるために区切り文字として使用されます。

column -t複数のスペースよりも優れたソート

答え2

次の(最適化されていない)正規表現を試してください。

$ sed 's/\(^.*\)\(\/[^ ]* \)\([^ ]* \)\([^ ]* \)\([^ ]*\)/\1 \3/' infile
wdiff 1.2.2-1build1 
wget 1.17.1-1ubuntu1.5 
whiptail 0.52.18-1ubuntu2 
xauth 1:1.0.9-1ubuntu2 
xdg-user-dirs 0.15-2ubuntu6.16.04.1 
xfsprogs 4.3.0+nmu1ubuntu1.1 
xkb-data 2.16-1ubuntu1 

関連情報