Linuxで正規表現を使用して特定のフィールドを印刷する

Linuxで正規表現を使用して特定のフィールドを印刷する

というファイルで、4番目のフィールド値が1001または1003の行を印刷しようとしていますmypasswd。正規表現にはgrepまたはegrepのみを使用できます。ファイルは次のようになります。

daemon:x:2:2:Daemon 1001:/sbin:/bin/bash
ftp:x:40:49:FTP export account:/srv/ftp:/bin/bash
daemonuser:x:50:59:nouser/bin/false:/home/nouser:/bin/bash
gdm:x:106:111:Gnome Display Mgr daemon:/var/lib/gdm:/bin/false
haldaemon:x:101:102:User for haldaemon:/var/run/hald:/bin/false
lp:x:4:7:Printing daemon:/var/spool/lpd:/bin/bash
mail:x:8:12:Mailer daemon:/var/spool/clientmqueue:/bin/false
root:x:0:0:root:/root:/bin/bash
sshd:x:71:65:SSH daemon:/var/lib/sshd:/bin/false
olivert:x:1001:1005:Tom Oliver:/home/olivert:/bin/csh
smiths:x:1049:1000:Sue Williams:/export/home/smiths:/bin/csh
northj:x:1003:1003:Jim jones-North:/home/northj:/bin/csh
denniss:x:1005:1003:Sue Dennis:/home/denniss:/bin/bash
smitha:x:1050:1001:Amy Smith:/export/home/smitha:/bin/bash
jonesc:x:1053:1001:Cathy Jones:/export/home/jonesc:/bin/ksh
smithd:x:1055:1001:Dan Smith Jr:/export/home/smithd:/bin/csh

したがって、出力は次のようになります

northj:x:1003:1003:Jim jones-North:/home/northj:/bin/csh
denniss:x:1005:1003:Sue Dennis:/home/denniss:/bin/bash
smitha:x:1050:1001:Amy Smith:/export/home/smitha:/bin/bash
jonesc:x:1053:1001:Cathy Jones:/export/home/jonesc:/bin/ksh
smithd:x:1055:1001:Dan Smith Jr:/export/home/smithd:/bin/csh

これは簡単に実行できますが、egrep '1001|1003' mypasswd「daemon」(5番目のフィールドに「1001」が含まれています)と「olivert」(3番目のフィールドが「1001」です)も提供されます。 egrep / grep regexを使用して、これら2つの数値の4番目のフィールド値(コロンの3つの後の値)を一致させるだけです。すべての回答は長期的にこの問題を解決するのに役立ちますので、大変感謝します。

答え1

私の考えでは、次のツールを使用する方が簡単ですawk

  • あなたのためのフィールド分割
  • 必要な値を取得したいフィールドを正確にテストしてください。

たとえば、

awk -F: '$4 == 1001 || $4 == 1003' mypasswd

...わかりました:

  • 着信行をコロンに基づいてフィールドに分割します。-F:
  • 「or」式を使用して、フィールド4の値が1001か1003かをテストします。
  • 上記の条件がtrueの場合、その行を印刷します(デフォルトの動作)。

awkを学ぶのに少し時間がかかります。理解すべき重要な点の1つは、「モード」と「作業」の文のペアを使用することです。 「モード」部分は、どの「ジョブ」ステートメントが実行されるかを決定します。

上記のawkをより明示的に書き換えることができます。これにより、必要なものを明示的に印刷できます(例:5番目のフィールド)。

awk -F: '$4 == 1001 || $4 == 1003 { print $5 }'

...または空の「モード」セクションがあります。つまり、「作業」を行うという意味です。すべて行を選択し、作業モード内で値をテストします。

awk -F: '{ if ($4 == 1001 || $4 == 1003)  print $5 }'

強制的にgrep対策を講じるには:

grep -E '^([^:]*:){3}(1001|1003):' mypasswd | cut -d: -f5

行の先頭から始まり、「コロン以外のすべての項目、回数制限なし」グループを3回見つけ、1001または1003を見つけて、一致する行全体を印刷するように指示します。その後、それを渡してcut5番目のフィールドのみを印刷します。

答え2

私はこれをすることができますsed

sed -n '/^.*:.*:.*:\(1001\|1003\):/p' mypasswd

行を抑制-nし、p最後に一致する行を印刷します。

また、これを行うことができますgrep

grep '^.*:.*:.*:1002\|1003:.*:.*:' mypasswd

答え3

@JeffSchallerが言ったように、このOPは私たちが2つを組み合わせることができることをawk望んでいたので、これがこれを行うためのツールです。regex

awk -F: '$4 ~ /^100[13]$/' mypasswd

grepこのバージョンでは、いくつかのゴルフパットが可能です。

grep -E "^(.*:){3}100[13]:" mypasswd

答え4

"egrep / grep regexを使用して、これら2つの数字の4番目のフィールド値(コロンの3つの後の値)を一致させるだけです。

4番目のフィールドのみが必要な場合は、次のcutように使用してくださいgrep

$ cat mypasswd | cut -d: -f4 | grep -E '^(1001|1003)$'
1001
1003

パターンgrepは行の始めと終わりに固定する必要があります。それ以外の場合は、同じ数字と一致する可能性があります10010。もう一つの方法はですgrep -x -E '1001|1003'

関連情報