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
...
答え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
通常、テキスト処理ツールを使用して、および同様のツールの出力を解析することは常に良い考えではありません。少なくとも移植性/互換性が必要な場合はそうではありませんdf
。ps
このような場合は、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