sed
andを使用するよりも複数の値列を取得するより高速な方法はありますか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
...