web-dev-qa-db-ja.com

sedやawkを使わずに、出力から特定の列を簡単に取得する

sedawkをいじくり回すよりも、いくつかの値の列を取得する簡単な方法はありますか?

たとえば、ls -hal /の出力があり、ファイルとディレクトリの名前とサイズだけを取得したい場合、easilyおよびquicklyを実行するにはどうすればよいですか、数分かけてコマンドを調整する必要はありません。

total 16078
drwxr-xr-x    33 root  wheel   1.2K Aug 13 16:57 .
drwxr-xr-x    33 root  wheel   1.2K Aug 13 16:57 ..
-rw-rw-r--     1 root  admin    15K Aug 14 00:41 .DS_Store
d--x--x--x     8 root  wheel   272B Jun 20 16:40 .DocumentRevisions-V100
drwxr-xr-x+    3 root  wheel   102B Mar 27 12:26 .MobileBackups
drwx------     5 root  wheel   170B Jun 20 15:56 .Spotlight-V100
d-wx-wx-wt     2 root  wheel    68B Mar 27 12:26 .Trashes
drwxrwxrwx     4 root  wheel   136B Mar 30 20:00 .bzvol
srwxrwxrwx     1 root  wheel     0B Aug 13 16:57 .dbfseventsd
----------     1 root  admin     0B Aug 16  2012 .file
drwx------  1275 root  wheel    42K Aug 14 00:05 .fseventsd
drwxr-xr-x@    2 root  wheel    68B Jun 20  2012 .vol
drwxrwxr-x+  289 root  admin   9.6K Aug 13 10:29 Applications
drwxrwxr-x     7 root  admin   238B Mar  5 20:47 Developer
drwxr-xr-x+   69 root  wheel   2.3K Aug 12 21:36 Library
drwxr-xr-x@    2 root  wheel    68B Aug 16  2012 Network
drwxr-xr-x+    4 root  wheel   136B Mar 27 12:17 System
drwxr-xr-x     6 root  admin   204B Mar 27 12:22 Users
drwxrwxrwt@    6 root  admin   204B Aug 13 23:57 Volumes
drwxr-xr-x@   39 root  wheel   1.3K Jun 20 15:54 bin
drwxrwxr-t@    2 root  admin    68B Aug 16  2012 cores
dr-xr-xr-x     3 root  wheel   4.8K Jul  6 13:08 dev
lrwxr-xr-x@    1 root  wheel    11B Mar 27 12:09 etc -> private/etc
dr-xr-xr-x     2 root  wheel     1B Aug 12 21:41 home
-rw-r--r--@    1 root  wheel   7.8M May  1 20:57 mach_kernel
dr-xr-xr-x     2 root  wheel     1B Aug 12 21:41 net
drwxr-xr-x@    6 root  wheel   204B Mar 27 12:22 private
drwxr-xr-x@   68 root  wheel   2.3K Jun 20 15:54 sbin
lrwxr-xr-x@    1 root  wheel    11B Mar 27 12:09 tmp -> private/tmp
drwxr-xr-x@   13 root  wheel   442B Mar 29 23:32 usr
lrwxr-xr-x@    1 root  wheel    11B Mar 27 12:09 var -> private/var

lsには何億ものオプションがあることに気づき、おそらくそれを行うことができますこの特定の例ではそのようにしていますが、これは一般的な問題であり、取得するための一般的な解決策が必要です特定のカラムを簡単かつ迅速に。

cutは、正規表現を使用しないため、切り捨てられません。また、列を区切るスペースが1つしかない状況は事実上ありません。これがうまくいけば完璧です:

ls -hal / | cut -d'\s' -f5,9

awksedは私が思っているよりも一般的で、基本的には言語全体が自分自身に当てはまります。私は彼らに対して何もしていません、私が最近彼らとたくさんやっているのでない限り、彼らの言葉で考え始め、うまくいくものを書くにはかなり大きなメンタルシフトが必要です。私は通常、解決しようとしている他の問題について考えている最中ですが、sed/awkの問題を突然解決しなければならない場合、焦点が外れます。

私が望むものを達成するための柔軟なショートカットはありますか?

4
iconoclast

理由はわかりません

ls -hal / | awk '{print $5, $9}'

あなたには、思考プロセスをはるかに混乱させるように思われます

ls -hal / | cut -d'\s' -f5,9

それがうまくいったら、そうだっただろう。本当にそれを書き留める必要がありますか? {}の追加が自動化されるまで、数行のawk行しかかかりません。 (私にとって最も難しい問題は、どのフィールド番号がどのデータに対応するかを覚えていることですが、おそらくその問題はありません。)

Awkの機能のallを使用する必要はありません。特定の列を単に出力するためには、awkをほとんど知る必要がありません。

苛立たしい問題は、ファイル名だけでなくシンボリックリンクを出力したい場合、またはファイル名にスペースが含まれている可能性がある場合でした。 (または、さらに悪いことに、改行)。架空の正規表現対応のカットでは、これは問題ではありません(改行を除く)。 -f5,9-f5,9-に置き換えるだけです。ただし、「フィールド9から最後まで」のawk構文はなく、forループの記述方法を覚えておく必要があります。

これは、cut-style -fオプションをawkプログラムに変換してから、awkプログラムを実行する小さなシェルスクリプトです。はるかに優れたエラーチェックが必要ですが、動作するようです。 (追加されたボーナス:awkプログラムに渡すことによって-dオプションを処理します。)

#!/bin/bash
prog=\{
while getopts f:d: opt; do
  case $opt in
    f) IFS=, read -ra fields <<<"$OPTARG"
       for field in "${fields[@]}"; do
         case $field in
           *-*) low=${field%-*}; high=${field#*-}
                if [[ -z $low  ]]; then low=1; fi
                if [[ -z $high ]]; then high=NF; fi
                ;;
            "") ;;
             *) low=$field; high=$field ;;
         esac
         if [[ $low == $high ]]; then
           prog+='printf "%s ", $'$low';'
         else
           prog+='for (i='$low';i<='$high';++i) printf "%s ", $i;'
         fi
       done
       prog+='printf "\n"}'
       ;;
    d) sep="-F$OPTARG";;
    *) exit 1;;
  esac
done
if [[ -n $sep ]]; then
  awk "$sep" "$prog"
else
  awk "$prog"
fi

クイックテスト:

$ ls -hal / | ./cut.sh -f5,9-
7.0K bin 
5.0K boot 
4.2K dev 
9.0K etc 
1.0K home 
8.0K Host 
33 initrd.img -> /boot/initrd.img-3.2.0-51-generic 
33 initrd.img.old -> /boot/initrd.img-3.2.0-49-generic 
...
9
rici

Sedやawkほど簡単な解決策はないと思います。ただし、独自の関数を作成することはできます。

リスト機能は次のとおりです(端末にコピーして貼り付けます)。

function list() { ls -hal $1 | awk '{printf "%-10s%-30s\n", $5, $9}'; }

次にリスト関数を使用します:

list /

list /etc
4
damphat

些細なことかもしれませんが、これはどうですか?

ls -hal / |
    while IFS=' ' read x x x x five x x x nine etc;
        do echo $five $nine;
    done

xfivenineおよびetc変数が最終的にサブシェルのスコープに含まれることを考慮に入れてください。 。:)

0
Dacav