web-dev-qa-db-ja.com

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

mypasswdというファイルから、4番目のフィールド値が1001または1003である行を印刷しようとしています。正規表現でのみ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ですが、「デーモン」(5番目のフィールドには「1001」が含まれています)と「オリバート」(3番目のフィールドは「1001」)も与えられます。 egrep/grep正規表現を使用して、これら2つの数値に一致する4番目のフィールド値(3つのコロンの後にある値)が必要です。これで長期的に私を助けてくれるので、どんな答えも大歓迎です。

8
Jake M

私の意見では、awkのようなツールを使用するほうがより直接的です。

  • あなたのためにフィールドを分割する
  • 必要な値に対して必要なフィールドを正確にテストする

例えば:

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

... awkに次のように伝えます。

  • -F:を使用して、入力行をコロンに基づいてフィールドに分割します
  • 「または」式を使用して、フィールド4の値が1001または1003かどうかをテストします
  • 上記の条件が真の場合、行を出力します(デフォルトのアクション)

Awkは少し習得できます。それについて理解する主要なことの1つは、「パターン」と「アクション」のペアのステートメントを使用することです。 「パターン」セクションは、どの「アクション」ステートメントが実行されるかを決定します。

上記のawkを書き換えて、より明確にすることができます。そうすることで、必要なもの(5番目のフィールドなど)を明示的に出力できます。

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

...または、空の「パターン」セクションを作成するには、つまり、「アクション」をevery行に対して実行し、アクションパターン内で値をテストします。

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

grepを強制的に実行するには、次のようにします。

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

行の最初から、「何でもないコロンは何回でも、その後はコロン」というグループを探して、3回続けて1001または1003を探し、次にコロン;一致する行全体を出力しますが、それをcutに渡して5番目のフィールドだけを出力します。

16
Jeff Schaller

sedでこれを行うかもしれません

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

-nは行を抑制し、最後のpは一致する行を出力します。

grepでそれを行うこともできます

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

@JeffSchallerが言うように、awkはジョブのツールであり、OPはregexを必要とするため、2つを組み合わせることができます

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

そして、それはgrepバージョンに小さなゴルフパットを許可します

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

必須のPerlソリューション:

フィールドを数値として解釈します。

Perl -F: -ane 'print if $F[3] == 1001 || $F[3] == 1003' mypasswd 

または正規表現を使用する

Perl -F: -ane 'print if $F[3] =~ /^(1001|1003)$/' mypasswd 

またはやや短い正規表現:

Perl -F: -ane 'print if $F[3] =~ /^100[13]$/' mypasswd 

または、算術を使っていくつかのトリックを実行します(これは少しこっそりです):

Perl -F: -ane 'print if abs($F[3] - 1002) == 1' mypasswd

オプションは次のとおりです:-a =配列に自動分割@F(インデックス作成はzeroで開始)、-F: = :をフィールド区切り文字として使用、-ne各行に対してここでスクリプトを実行します

行の始め/終わりへのアンカー(^および$)は、11001または10010のような数値が一致しないようにするために必要です。

2
ilkkachu

"egrep/grep正規表現を使用してこれらの2つの数値と一致する4番目のフィールド値(3つのコロンの後にある値)が必要です"

4番目のフィールドだけが必要な場合は、cutgrepを次のように使用します。

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

grepパターンは、行の最初と最後にアンカーする必要があります。それ以外の場合は、10010のような数字と一致する可能性があります。これを行う別の方法は、grep -x -E '1001|1003'です。

2
mjoao

コメント(削除済み)

これを機能させるには、行全体を印刷する必要がありますが、4番目のフィールド値を強調表示する必要があります。

唯一のgrepは、「フィールド値」を「強調表示」して、色を付けることです。そうしたい場合は、拡張 StéphaneChazelasの調整 オン ilkkachuの調整 オン StrongBadの回答 を拡張できます。

_grep -E '^[^:]*:[^:]*:[^:]*:(1001|1003):[^:]*:[^:]*:' mypasswd
_

(これがGNU grepであると仮定すると、これはLinuxでは通常のことです)PCREマジックを追加します。

_grep --color -P '^[^:]*:[^:]*:[^:]*:\K(1001|1003)(?=:[^:]*:[^:]*:)' mypasswd
_

_\K_は、これまでの正規表現で一致したテキストが、正規表現の一致から除外されます。 (?=regex)は(正の)先読みです。 _1001_または_1003_は、その後にコロンと3つのフィールドが続く場合にのみ一致する必要があることを示しています。

問題の入力ファイルが与えられると、上記のコマンドは次の出力を生成します。

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:キャシー・ジョーンズ:/ export/home/jonesc:/ bin/ksh 
 smithd:x:1055:1001:Dan Smith Jr:/ export/home/smithd:/ bin/csh

太字の斜体のテキストに色を付けています。

次に、passwdファイルで機能する別のバージョンを示します。

 grep -E --color=auto ':[[:alnum:]]+:[[:digit:]]+:(1001|1003):' mypasswd

説明:

  • grep -Eは拡張正規表現を有効にするため、(1001|1003)でOR構文を使用できます。 (-Eを追加したことによるもう1つの結果は、+およびその他の特殊文字をエスケープする必要がないことです。)
  • --color=autoは完全にオプションです。一致した文字列に色を付けるだけです。
  • ':[[:alnum:]]+:[[:digit:]]+:(1001|1003):'は、コロン、1つ以上の英数字、コロン、1つ以上の数字、コロン、1001または1003の順に続く文字列に一致します。結腸。 (2番目のフィールドがalways "x"であるコンテキストでは、[[:graph:]]+xに置き換えることができます。)
  • 最初の列の内容については何も想定していないので、最初のコロンの前には何もありません。

質問のサンプルデータの場合、これは次の出力を提供します(カラーリングは削除されています)。

 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
1
Tsundoku

3回ホップして、3番目の結腸に止まる。次に、中断したところから検索を実行し、コロンを押す前に1001または1003を探します。検索が成功した場合は、行を印刷します。

$ Perl -ne ' /:/g;//g;//g;/\G100[13]:/&&print' file

Gnu sed

$ sed -e 'h;s/:/\n/4;/:100[13]\n/!d;g' file 
0
Rakesh Sharma