web-dev-qa-db-ja.com

bash:出力のn番目の列を取得する最短の方法

勤務時間中に、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番目の列コマンド出力を取得する方法です。ありがとう:)

132
Sv1

cut を使用して、2番目のフィールドにアクセスできます。

cut -f2

編集:申し訳ありませんが、SVNはその出力でタブを使用しないことに気づかなかったので、それは少し役に立たないです。 cutを出力に合わせることができますが、少し壊れやすいです。cut -c 10-のようなものが機能しますが、正確な値は設定によって異なります。

別のオプションは次のようなものです:sed 's/.\s\+//'

95
porges

以下と同じことを達成するには:

svn st | awk '{print $2}' | xargs rm

bashのみを使用すると、次を使用できます。

svn st | while read a b; do rm "$b"; done

確かに、短くはありませんが、もう少し効率的で、ファイル名の空白を正しく処理します。

83
Rick Sladkey

私は同じ状況にいることに気付き、これらのエイリアスを.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
25
StackedCrooked

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クリス

15
Chris

スクリプトに慣れていないように見えるため、ここに例を示します。

#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=$1
shift
awk -v col="$col" '{print $col}' "${@--}"

これを~/bin/xに保存し、~/binPATHにあることを確認すると(これが.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は使用しないでください)。

7
tripleee

すでに解決策があるようです。物事を簡単にするために、コマンドをbashスクリプト(短い名前)に入れて、その「長い」コマンドを毎回入力するのではなく、単に実行してみませんか?

5
Tarek Fadel

列を手動で選択しても問題ない場合は、 pick を使用すると非常に高速になります。

svn st | pick | xargs rm

2列目の任意のセルに移動し、cを押してからenterを押す

2
Bernardo Rufino

ファイルパスは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パーサーを使用することもできます。

1
Michał Šrajer