勤務時間中に、bashのコマンドから次の形式の列化された出力に繰り返し遭遇したとします(私の場合、Rails作業ディレクトリでsvn st
を実行したとき)。
? changes.patch
M app/models/superman.rb
A app/models/superwoman.rb
コマンドの出力(この場合はファイル名)を操作するには、2番目の列を次のコマンドの入力として使用できるように、何らかの解析が必要です。
私がやっていることは、awk
を使用して2番目の列を取得することですすべてのファイルを削除したいとき(それは典型的なユースケースではありません):
svn st | awk '{print $2}' | xargs rm
私はこれをたくさん入力するので、自然な質問は次のとおりです:bashでこれを達成するためのより短い(よりクールな)方法はありますか?
注:具体的な例はsvnワークフローにありますが、私が尋ねているのは本質的にシェルコマンドの質問です。ワークフローが馬鹿げていると感じ、代替アプローチを提案する場合、おそらくあなたは投票しませんが、他の人は、ここでの質問は実際に可能な限り最短の方法でn番目の列コマンド出力を取得する方法です。ありがとう:)
cut
を使用して、2番目のフィールドにアクセスできます。
cut -f2
編集:申し訳ありませんが、SVNはその出力でタブを使用しないことに気づかなかったので、それは少し役に立たないです。 cut
を出力に合わせることができますが、少し壊れやすいです。cut -c 10-
のようなものが機能しますが、正確な値は設定によって異なります。
別のオプションは次のようなものです:sed 's/.\s\+//'
以下と同じことを達成するには:
svn st | awk '{print $2}' | xargs rm
bashのみを使用すると、次を使用できます。
svn st | while read a b; do rm "$b"; done
確かに、短くはありませんが、もう少し効率的で、ファイル名の空白を正しく処理します。
私は同じ状況にいることに気付き、これらのエイリアスを.profile
ファイルに追加しました。
alias c1="awk '{print \$1}'"
alias c2="awk '{print \$2}'"
alias c3="awk '{print \$3}'"
alias c4="awk '{print \$4}'"
alias c5="awk '{print \$5}'"
alias c6="awk '{print \$6}'"
alias c7="awk '{print \$7}'"
alias c8="awk '{print \$8}'"
alias c9="awk '{print \$9}'"
次のようなものを書くことができます:
svn st | c2 | xargs rm
Zshを試してください。サフィックスエイリアスをサポートしているため、.zshrcでXを次のように定義できます。
alias -g X="| cut -d' ' -f2"
その後、次のことができます:
cat file X
さらに一歩進んで、n番目の列に定義できます。
alias -g X2="| cut -d' ' -f2"
alias -g X1="| cut -d' ' -f1"
alias -g X3="| cut -d' ' -f3"
ファイル "file"のn番目の列を出力します。これは、grep出力またはそれ以下の出力に対しても実行できます。これは非常に便利で、zshのすばらしい機能です。
さらに一歩進んで、Dを次のように定義できます。
alias -g D="|xargs rm"
次のように入力できます:
cat file X1 D
ファイル「file」の最初の列に記載されているすべてのファイルを削除します。
Bashを知っている場合、zshはいくつかの新機能を除いてあまり変更されていません。
HTHクリス
スクリプトに慣れていないように見えるため、ここに例を示します。
#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=$1
shift
awk -v col="$col" '{print $col}' "${@--}"
これを~/bin/x
に保存し、~/bin
がPATH
にあることを確認すると(これが.bashrc
に入れることができます)、一般に列nを抽出するための最短のコマンドがあります。 x n。
スクリプトは、数値以外の引数または引数の数が正しくないなどで呼び出された場合、適切なエラーチェックと保釈を行う必要があります。ただし、この最低限の必須バージョンの拡張はユニット102で行われます。
別の列区切り文字を許可するようにスクリプトを拡張することもできます。デフォルトでは、awkは入力を空白のフィールドに解析します。別の区切り文字を使用するには、-F ':'
を使用します。ここで、:
は新しい区切り文字です。これをスクリプトのオプションとして実装すると、少し長くなりますので、読者の演習として残しておきます。
ファイルfile
が与えられた場合:
1 2 3
4 5 6
Stdin経由で渡すことができます( 役に立たないcat
を単にもっと便利なもののプレースホルダーとして使用します)。
$ cat file | sh script.sh 2
2
5
または、スクリプトの引数として指定します。
$ sh script.sh 2 file
2
5
ここで、sh script.sh
は、スクリプトが現在のディレクトリにscript.sh
として保存されていると想定しています。上記の手順のように、PATH
のどこかにもっと便利な名前で保存し、実行可能とマークする場合は、代わりに便利な名前を使用してください(sh
は使用しないでください)。
すでに解決策があるようです。物事を簡単にするために、コマンドをbashスクリプト(短い名前)に入れて、その「長い」コマンドを毎回入力するのではなく、単に実行してみませんか?
ファイルパスはsvn st出力の2列目にある必要はありません。たとえば、ファイルを変更し、そのプロパティを変更すると、3列目になります。
以下の可能な出力例を参照してください。
svn help st
出力例:
M wc/bar.c
A + wc/qax.c
次の方法で最初の8文字をカットすることをお勧めします。
svn st | cut -c8- | while read FILE; do echo whatever with "$FILE"; done
100%確実であり、たとえば末尾に空白を含む空想的なファイル名を扱う場合は、xml出力を解析する必要があります。
svn st --xml | grep -o 'path=".*"' | sed 's/^path="//; s/"$//'
もちろん、grep/sedではなく、実際のXMLパーサーを使用することもできます。