sedまたはawkなしで出力から特定の列を簡単に取得します。

sedまたはawkなしで出力から特定の列を簡単に取得します。

sedandを使用するよりも複数の値列を取得するより高速な方法はありますかawk

たとえば、出力があり、ls -hal /ファイルとディレクトリの名前とサイズのみをインポートしたい場合はどうすればよいですか?簡単にそして早くコマンドを変更するのに数分を費やすことなく、これを行うことができます。

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正規表現を必要とせず、列が単一のスペースで区切られる状況はほとんど発生しないため、切り捨てません。うまくいけば完璧でしょう。

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

awkそしてsed私が望むものよりも一般的です。基本的には言語全体です。私は彼らに反対するつもりはありません。私が最近彼らと多くのことをしていない限り、彼らのやり方で考えて役に立つ文章を書き始めるには、かなりの精神的な変化が必要だということです。私は通常解決しようとしている他の問題について考えていますが、突然1つsed/awk問題を解決しなければ注意が気になります。

私が望むことを達成するための柔軟な近道はありますか?

答え1

なぜかはわかりませんが

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

あなたの意見では、これはあなたの思考プロセスでより破壊的なものよりも

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

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

使用する必要はありませんみんなawkの機能:単に特定の列を出力するには、awkについてほとんど知っておく必要があります。

迷惑な問題は、ファイル名とともにシンボリックリンクを出力したい場合、またはファイル名にスペースがある可能性があることです。 (またはさらに悪くは改行文字)。仮定された正規表現認識クリッピングを使用しても問題になりません(改行を除く)-f5,9-f5,9-しかし、「フィールド9から最後まで」にはawk構文がないので、forループを書く方法を覚えておく必要があります。 。

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

#!/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 
...

答え2

私はsedやawkよりも簡単な解決策はないと思います。しかし、独自の関数を書くことができます。

リスト機能は次のとおりです(ターミナルにコピーして貼り付け)。

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

その後、リスト機能を使用します。

list /

list /etc

答え3

熱が何であるかを説明せずに「熱」についてだけ話すことはできません!

Unixテキスト処理では、スペースを列(フィールド)区切り文字として使用し、(自然)改行文字を行またはレコード区切り文字として使用するのが非常に一般的です。以下awkは読みやすい優れたツールです。

# for words (columns) 5 and 9:
ls -lah | awk '{print $5 " " $9}'
# or this, for the fifth and the last word:
ls -lah | awk '{print $5 " " $NF}'

列を文字で並べ替えると良いでしょうcut -c

ls -lah | cut -c 31-33,46-

awkこのオプションを使用すると、他のフィールド区切り文字を使用できます-F。で-c(または-b)を使用しない場合をcut使用して、-f出力する列を指定します。

秘訣は入力を理解することです。

ls通常、テキスト処理ツールを使用して、および同様のツールの出力を解析することは常に良い考えではありません。少なくとも移植性/互換性が必要な場合はそうではありませんdfpsこのような場合は、POSIX定義形式で出力を強制してみてください。場合によっては-P、出力を生成するコマンドにいくつかのオプション(おそらく)を渡すことでこれを達成できます。時には環境変数(例:)を設定するか、POSIXLY_CORRECT特定のバイナリ(例:/usr/xpg4/bin/ls

答え4

これについて誰も書いていないのは驚くべきことですが、cut繰り返される空白を単一の区切り文字として扱わないことが唯一の反対であれば、繰り返される空白をただ絞るのはどうですか?これはその用途の1つですtr

ls -l | tr -s ' ' | cut -d ' ' -f5,9

あなたの質問に表示される出力を考慮すると、ls -l結果は次のようになります。

1.2K .
1.2K ..
15K .DS_Store
272B .DocumentRevisions-V100
102B .MobileBackups
170B .Spotlight-V100
68B .Trashes
136B .bzvol
0B .dbfseventsd
0B .file
42K .fseventsd
68B .vol
9.6K Applications
238B Developer
2.3K Library
68B Network
136B System
204B Users
204B Volumes
1.3K bin
68B cores
4.8K dev
11B etc
1B home
7.8M mach_kernel
1B net
204B private
2.3K sbin
11B tmp
442B usr
11B var

関連情報