/etc/passwdからgrepを使用してリストされているすべてのユーザーのホームディレクトリを見つける必要があります

/etc/passwdからgrepを使用してリストされているすべてのユーザーのホームディレクトリを見つける必要があります

このサイトにある別の質問と似た質問があります。その質問では、/etc/passwd から grep または awk を使用してすべてのユーザーのリストを探す必要がありました。私の場合はうまくいきましたが、ホーム ディレクトリも検索してリストするように変換してみました。1 行ではできないことは既にわかっているので、パイプラインを使用することはわかっています。オンラインで調査しましたが、問題が何なのかわかりません。grep を使用して、次のような操作を行うと、次のようになります。

   grep -oE '^[/*/]$' /etc/passwd 

...おそらくエラーが発生するか、/bin/bash ファイルも表示されますが、これは私が望んでいることではありません。必要なのは、grep を使用してリストされたユーザー名とホーム ディレクトリだけです。また、ホーム ディレクトリによっては / (スラッシュ) が 2 つ以上あるため、* が他のスラッシュを文字として表示するかどうかもわかりません。

答え1

使用できますcut特定の区切り文字で列を分割するには:

cut -d: -f6 /etc/passwd

または、-f1,6列 (​​フィールド) 1 と 6 の場合。

答え2

Grep は実際にはこのようにデータを解析するためのツールではありません。grep はパターン マッチング用であり、テキスト処理を実行しようとしています。awk を使用することをお勧めします。

awk -F":" '$7 == "/bin/false" {print "User: "$1 "Home Dir: "$6}' /etc/passwd
  • awk- コマンド

  • -F":"– データ区切り文字を:

  • $7 == "/bin/false"– 7番目のデータ列が/bin/false

  • {print "User: "$1 "Home Dir: "$6}'– 最初の列と 6 番目の列を指定された形式で印刷するように指示します。

  • /etc/passwd– 処理中のファイルは

答え3

他の人が指摘しているように、grepこれはこの目的に最適なツールではありません。どうしてもこのツールを使いたい場合、(行の一致した部分のみを印刷) と(Perl 互換の正規表現を使用) をgrepサポートしている場合は、次のようにします。-o-P

$ grep -oP '^[^:]+|.*:\K[^:]+(?=:[^:]+)' /etc/password
terdon
/home/terdon
bob
/home/bob

これにより、システム ユーザーを含むすべてのユーザーが印刷されることに注意してください。ここでは例として 4 行のみを示しています。

これにより、すべてのユーザーのユーザー名とホーム ディレクトリが別々の行に印刷されます。次に、各行のペアを結合して 1 つにまとめる必要があります。

$ grep -oP '^[^:]+|.*:\K[^:]+(?=:[^:]+)' /etc/passwd | perl -pe 's/\n/ : / if $.%2'
root : /root
bin : /bin
daemon : /
mail : /var/spool/mail
ftp : /srv/ftp
http : /srv/http
uuidd : /
dbus : /
nobody : /
systemd-journal-gateway : /
systemd-timesync : /
systemd-network : /
systemd-bus-proxy : /
systemd-resolve : /
systemd-journal-upload : /
systemd-coredump : /
systemd-journal-remote : /
terdon : /home/terdon
avahi : /
polkitd : /
colord : /var/lib/colord
rtkit : /proc
gdm : /var/lib/gdm
git : /
bob : /home/bob

説明

正規表現には 2 つの部分があり、^[^:]+OR を検索します (これが の意味です|) 。最初の部分は、行の先頭から.*:\K[^:]+(?=:[^:]+)1 つ以上の非 文字を検索します。これはユーザー名と一致します。2 番目の部分は、 ( ) まで可能な限り多くの文字を検索し、その後それらを破棄して (これが の機能です)、印刷されないようにします。次に、非 の文字列に一致し、その後に非 が続きます。この構造は と呼ばれます。::.*:\K:::(?=foo)ポジティブ先読み文字を一致させる方法です一致自体にそれらの文字を含めないパターン。

このコマンドは、現在の行番号 ( ) が 2 で割り切れる場合、perl改行を と スペースに置き換えます。つまり、2 行ごとに 1 行ずつです。:$.

答え4

「cut」を使用すると、バイナリを 1 つだけ使用し、パイプを回避して、他の回答と同じ結果をよりエレガントな方法で得ることができると思います。

$ cut -d : -f 1,6 /etc/passwd

root:/root
daemon:/usr/sbin
bin:/bin
sys:/dev
sync:/bin
games:/usr/games
man:/var/cache/man
lp:/var/spool/lpd
mail:/var/mail
news:/var/spool/news
....

出力をより適切にフォーマットし、アルファベット順にしたい場合は、次のようになります。ただし、トレードオフとして、より多くのバイナリを使用する必要があります。

$ cut -d : -f 1,6 /etc/passwd | sort | column

avahi-autoipd:/var/lib/avahi-autoipd        man:/var/cache/man
avahi:/var/run/avahi-daemon                 messagebus:/var/run/dbus
backup:/var/backups                         news:/var/spool/news
bin:/bin                                    nobody:/nonexistent
clickpkg:/nonexistent                       ntp:/home/ntp
colord:/var/lib/colord                      proxy:/bin
daemon:/usr/sbin                            pulse:/var/run/pulse
dnsmasq:/var/lib/misc                       root:/root
games:/usr/games                            rtkit:/proc
gnats:/var/lib/gnats                        saned:/home/saned
hplip:/var/run/hplip                        speech-dispatcher:/var/run/speech-dispatcher
irc:/var/run/ircd                           sync:/bin
ivanleon:/home/ivanleon                     sys:/dev
kernoops:/                                  syslog:/home/syslog
libuuid:/var/lib/libuuid                    usbmux:/home/usbmux
lightdm:/var/lib/lightdm                    usermetrics:/var/lib/usermetrics
list:/var/list                              uucp:/var/spool/uucp
lp:/var/spool/lpd                           whoopsie:/nonexistent
lxc-dnsmasq:/var/lib/lxc                    www-data:/var/www
mail:/var/mail

関連情報