web-dev-qa-db-ja.com

awkを使用してn番目から最後までのすべての列を印刷する

この行は、2番目のフィールドに空白が入るまで機能しました。

svn status | grep '\!' | gawk '{print $2;}' > removedProjs

awkにすべてを2ドル以上で印刷させる方法はありますか? ($ 3、$ 4 ..もう列がなくなるまで)

私はCygwinを使ってWindows環境でこれをやっていることを付け加えるべきだと思います。

267
Andy

最初の列を除くすべての列を印刷します。

awk '{$1=""; print $0}' somefile

最初の2列を除くすべての列を印刷します。

awk '{$1=$2=""; print $0}' somefile
421
zed_0xff

Cutを使った 簡単な答え の重複する質問があります。

 svn status |  grep '\!' | cut -d\  -f2-

-dは区切り文字(スペース)を指定し、-fは列のリストを指定します(すべて2番目から始まります)

90
Joshua Goldberg

Forループを使用して、$ 2から$ NFまでのフィールドを印刷することができます(行のフィールド数を表す組み込み変数)。

編集: "print"は改行を追加するので、結果をバッファしたいでしょう。

awk '{out=""; for(i=2;i<=NF;i++){out=out" "$i}; print out}'

あるいは、printfを使用してください。

awk '{for(i=2;i<=NF;i++){printf "%s ", $i}; printf "\n"}'
76
VeeArr
awk '{out=$2; for(i=3;i<=NF;i++){out=out" "$i}; print out}'

私の答えは VeeArr のものに基づいています、しかし私はそれが2番目の列(そして残りの部分)をプリントする前に空白で始まったことに気づきました。私は1つの評判ポイントしか持っていないので、私はそれについてコメントすることができません、それでここでそれは新しい答えとして行きます:

2番目の列として "out"で始めて、それから他のすべての列を追加します(存在する場合)。 2番目の列がある限り、これはうまくいきます。

23
Wim

私は個人的に上記のすべての答えを試してみましたが、それらのほとんどは少し複雑であるか、または正しくないだけでした。私の視点からそれを行う最も簡単な方法は次のとおりです。

awk -F" " '{ for (i=4; i<=NF; i++) print $i }'
  1. ここで、-F ""はawkが使う区切り文字を定義します。私の場合は空白文字ですが、これはawkのデフォルトの区切り文字でもあります。これは-F ""を無視できることを意味します。

  2. ここで、NFはフィールド/列の総数を定義します。したがって、ループは4番目のフィールドから最後のフィールド/列まで始まります。

  3. $ NがN番目のフィールドの値を取得する場所。したがって、print $ iは、ループ回数に基づいて現在のフィールド/列を印刷します。

12
koullislp

Awkを使ったほとんどの解決策はスペースを残します。ここのオプションはその問題を回避します。

オプション1

単純なカットソリューション(単一の区切り文字でのみ機能します):

command | cut -d' ' -f3-

オプション2

Awkの再計算を強制すると、最初のフィールドを削除することで残っている先頭のスペース(OFS)を削除することがあります(awkのいくつかのバージョンで動作します)。

command | awk '{ $1=$2="";$0=$0;} NF=NF'

オプション3

printfでフォーマットされた各フィールドを印刷すると、さらに制御が容易になります。

$ in='    1    2  3     4   5   6 7     8  '
$ echo "$in"|awk -v n=2 '{ for(i=n+1;i<=NF;i++) printf("%s%s",$i,i==NF?RS:OFS);}'
3 4 5 6 7 8

ただし、これまでのすべての回答では、フィールド間で繰り返されるすべてのFSをOFSに変更しています。それをしないいくつかのオプションを作りましょう。

オプション4(推奨)

前のフィールドと区切り文字を削除するためのsubを持つループ。
そして、スペースの代わりにFSの値を使用します(これは変更可能です)。
移植性が高く、FSからOFSへの変更をトリガーしません。注:^[FS]*は先行スペースを含む入力を受け入れます。

$ in='    1    2  3     4   5   6 7     8  '
$ echo "$in" | awk '{ n=2; a="^["FS"]*[^"FS"]+["FS"]+";
  for(i=1;i<=n;i++) sub( a , "" , $0 ) } 1 '
3     4   5   6 7     8

オプション5

以下のように、GNU awkの関数gensubを使用して、余分な(先頭または末尾の)空白を追加しないソリューションを構築し、既存の空白を保持することは可能です。

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=2 'BEGIN{ a="^["FS"]*"; b="([^"FS"]+["FS"]+)"; c="{"n"}"; }
          { print(gensub(a""b""c,"",1)); }'
3     4   5   6 7     8 

Count nを与えられたフィールドのグループを交換するためにも使用されます。

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=2 'BEGIN{ a="^["FS"]*"; b="([^"FS"]+["FS"]+)"; c="{"n"}"; }
          {
            d=gensub(a""b""c,"",1);
            e=gensub("^(.*)"d,"\\1",1,$0);
            print("|"d"|","!"e"!");
          }'
|3     4   5   6 7     8  | !    1    2  !

もちろん、そのような場合、OFSは行の両方の部分を分離するために使用され、フィールドの末尾の空白はまだ印刷されます。

注:[FS]*は、入力行の先頭にスペースを入れるために使用されます。

12
user2350426

これは私をとても苛立たせていました。私は座って、GNU Awk 3.1.7でテストされたcut-likeフィールド仕様パーサーを書きました。

まず、pfcutという新しいAwkライブラリスクリプトを作成します。

Sudo nano /usr/share/awk/pfcut

次に、以下のスクリプトを貼り付けて保存します。その後、使い方は次のようになります。

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-4"); }'
t1 t2 t3 t4

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("2-"); }'
t2 t3 t4 t5 t6 t7

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

すべて入力するのを避けるために、私ができる最善の方法があると思います(そうでない場合は awkを使って起動時にユーザー関数を自動的にロードしますか? - Unix&Linux Stack Exchange~/.bashrcにエイリアスを追加します。例えばと:

$ echo "alias awk-pfcut='awk -f pfcut --source'" >> ~/.bashrc
$ source ~/.bashrc     # refresh bash aliases

...それからあなたはただ呼ぶことができます:

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk-pfcut '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

これがpfcutスクリプトのソースです。

# pfcut - print fields like cut
#
# sdaau, GNU GPL
# Nov, 2013

function spfcut(formatstring)
{
  # parse format string
  numsplitscomma = split(formatstring, fsa, ",");
  numspecparts = 0;
  split("", parts); # clear/initialize array (for e.g. `tail` piping into `awk`)
  for(i=1;i<=numsplitscomma;i++) {
    commapart=fsa[i];
    numsplitsminus = split(fsa[i], cpa, "-");
    # assume here a range is always just two parts: "a-b"
    # also assume user has already sorted the ranges
    #print numsplitsminus, cpa[1], cpa[2]; # debug
    if(numsplitsminus==2) {
     if ((cpa[1]) == "") cpa[1] = 1;
     if ((cpa[2]) == "") cpa[2] = NF;
     for(j=cpa[1];j<=cpa[2];j++) {
       parts[numspecparts++] = j;
     }
    } else parts[numspecparts++] = commapart;
  }
  n=asort(parts); outs="";
  for(i=1;i<=n;i++) {
    outs = outs sprintf("%s%s", $parts[i], (i==n)?"":OFS); 
    #print(i, parts[i]); # debug
  }
  return outs;
}

function pfcut(formatstring) {
  print spfcut(formatstring);
}
6
sdaau

これでうまくいくでしょうか。

awk '{print substr($0,length($1)+1);}' < file

それはしかし前にいくつかの空白を残します。

5
whaley

#2から始まる列を出力します(出力の先頭に末尾スペースはありません)

ls -l | awk '{sub(/[^ ]+ /, ""); print $0}'
5
savvadia
echo "1 2 3 4 5 6" | awk '{ $NF = ""; print $0}'

これは、最後のフィールド以外のすべてを印刷するためにawkを使います

4
Kaushal Jha
awk '{ for(i=3; i<=NF; ++i) printf $i""FS; print "" }'

lauhub は、この正確で単純かつ高速な解決策を提案しました こちら

4
ajendrex

これは私がすべての勧告から好むものです:

6列目から最後の列までの印刷。

ls -lthr | awk '{out=$6; for(i=7;i<=NF;i++){out=out" "$i}; print out}'

または

ls -lthr | awk '{ORS=" "; for(i=6;i<=NF;i++) print $i;print "\n"}'
3
Manuel Parra

特定の列を任意の区切り文字で印刷する必要がある場合

awk '{print $3 "  " $4}'

コル#3コル#4

awk '{print $3 "anything" $4}'

col#3anythingcol#4

そのため、列に空白がある場合は2列になりますが、任意の区切り文字で接続してもしなくてもかまいません。

2
I159

Perlソリューション:

Perl -lane 'splice @F,0,1; print join " ",@F' file

これらのコマンドラインオプションが使用されます。

  • -nは入力ファイルのすべての行をループします。すべての行を自動的には表示しません

  • -lは処理前に改行を削除し、その後それらを追加し直します

  • -a自動分割モード - 入力行を@F配列に分割します。空白で分割するデフォルト

  • -eはPerlコードを実行します

splice @F,0,1は@F配列から列0をきれいに削除します

join " ",@Fは、各要素の間にスペースを入れて@F配列の要素を結合します


Pythonソリューション:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[1:]) + '\n') for line in sys.stdin]" < file

2
Chris Koknat

これはあなたがBashを使っていて、あなたが捨てたい要素と同じ数の 'x'を使うことができ、それらがエスケープされていなければ無視します。

while read x b; do echo "$b"; done < filename
0
Stuart Rothrock

このawk関数は、beginからendまでのフィールドを含む$0のサブストリングを返します。

function fields(begin, end,    b, e, p, i) {
    b = 0; e = 0; p = 0;
    for (i = 1; i <= NF; ++i) {
        if (begin == i) { b = p; }
        p += length($i);
        e = p;
        if (end == i) { break; }
        p += length(FS);
    }
    return substr($0, b + 1, e - b);
}

フィールド3からすべてを取得するには

tail = fields(3);

フィールド3から5までをカバーする$0のセクションを取得するには、次のようにします。

middle = fields(3, 5);

関数パラメータリストのb, e, p, iナンセンスは、ローカル変数を宣言する単なるawkの方法です。

0
wonder.mice

Perl:

@m=`ls -ltr dir | grep ^d | awk '{print \$6,\$7,\$8,\$9}'`;
foreach $i (@m)
{
        print "$i\n";

}
0
pkm

あなたが切り落とさない部分の行を再フォーマットしたくない場合は、私が考えることができる最善の解決策は私の答えで書かれています:

awkを使って特定の数字の後にすべての列を表示するにはどうすればいいですか?

与えられたフィールド番号Nの前にあるものを切り落とし、フィールド番号Nを含め、元の間隔を維持しながら行の残りすべてを印刷します(再フォーマットはしません)。フィールドの文字列が行内の他の場所にも表示されても問題ありません。

関数を定義します。

fromField () { 
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

そしてこれを次のように使います。

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 

末尾のスペースを含め、出力はすべてを維持します

あなたの特定のケースでは:

svn status | grep '\!' | fromField 2 > removedProjs

ファイル/ストリームの行の途中に改行文字が含まれていない場合は(別のレコード区切り文字を使用している可能性があります)、次のようにします。

awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

最初のケースはまれな16進文字数1を含むファイル/ストリームでのみ失敗します。

0
Robert Vila

私は提案された答えを、場合によっては数個の空白で区切られている状況に拡張したい - OPがcutname__を使用していない理由。

私はOPがawkname__について尋ねたことを知っていますが、sedname__アプローチはここでうまくいくでしょう(5番目から最後まで列を印刷する例):

  • 純粋なsedのアプローチ

    sed -r 's/^\s*(\S+\s+){4}//' somefile
    

    説明:

    • s///は、置換を実行するための標準的な方法です。
    • ^\s*は、行頭の任意の連続した空白に一致します
    • \S+\s+は、データの列を意味します(非空白文字とそれに続く空白文字)。
    • (){4}は、パターンが4回繰り返されることを意味します。
  • セッドアンドカット

    sed -r 's/^\s+//; s/\s+/\t/g' somefile | cut -f5-
    

    連続した空白を1つのタブに置き換えるだけです。

  • tr and cut:trname__は、 -sオプションで の連続した文字を圧縮するためにも使用できます。

    tr -s [:blank:] <somefile | cut -d' ' -f5-
    
0
PlasmaBinturong