この行は、2番目のフィールドに空白が入るまで機能しました。
svn status | grep '\!' | gawk '{print $2;}' > removedProjs
awkにすべてを2ドル以上で印刷させる方法はありますか? ($ 3、$ 4 ..もう列がなくなるまで)
私はCygwinを使ってWindows環境でこれをやっていることを付け加えるべきだと思います。
最初の列を除くすべての列を印刷します。
awk '{$1=""; print $0}' somefile
最初の2列を除くすべての列を印刷します。
awk '{$1=$2=""; print $0}' somefile
Cutを使った 簡単な答え の重複する質問があります。
svn status | grep '\!' | cut -d\ -f2-
-d
は区切り文字(スペース)を指定し、-f
は列のリストを指定します(すべて2番目から始まります)
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"}'
awk '{out=$2; for(i=3;i<=NF;i++){out=out" "$i}; print out}'
私の答えは VeeArr のものに基づいています、しかし私はそれが2番目の列(そして残りの部分)をプリントする前に空白で始まったことに気づきました。私は1つの評判ポイントしか持っていないので、私はそれについてコメントすることができません、それでここでそれは新しい答えとして行きます:
2番目の列として "out"で始めて、それから他のすべての列を追加します(存在する場合)。 2番目の列がある限り、これはうまくいきます。
私は個人的に上記のすべての答えを試してみましたが、それらのほとんどは少し複雑であるか、または正しくないだけでした。私の視点からそれを行う最も簡単な方法は次のとおりです。
awk -F" " '{ for (i=4; i<=NF; i++) print $i }'
ここで、-F ""はawkが使う区切り文字を定義します。私の場合は空白文字ですが、これはawkのデフォルトの区切り文字でもあります。これは-F ""を無視できることを意味します。
ここで、NFはフィールド/列の総数を定義します。したがって、ループは4番目のフィールドから最後のフィールド/列まで始まります。
$ NがN番目のフィールドの値を取得する場所。したがって、print $ iは、ループ回数に基づいて現在のフィールド/列を印刷します。
Awkを使ったほとんどの解決策はスペースを残します。ここのオプションはその問題を回避します。
単純なカットソリューション(単一の区切り文字でのみ機能します):
command | cut -d' ' -f3-
Awkの再計算を強制すると、最初のフィールドを削除することで残っている先頭のスペース(OFS)を削除することがあります(awkのいくつかのバージョンで動作します)。
command | awk '{ $1=$2="";$0=$0;} NF=NF'
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に変更しています。それをしないいくつかのオプションを作りましょう。
前のフィールドと区切り文字を削除するための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
以下のように、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]*
は、入力行の先頭にスペースを入れるために使用されます。
これは私をとても苛立たせていました。私は座って、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);
}
これでうまくいくでしょうか。
awk '{print substr($0,length($1)+1);}' < file
それはしかし前にいくつかの空白を残します。
#2から始まる列を出力します(出力の先頭に末尾スペースはありません)
ls -l | awk '{sub(/[^ ]+ /, ""); print $0}'
echo "1 2 3 4 5 6" | awk '{ $NF = ""; print $0}'
これは、最後のフィールド以外のすべてを印刷するためにawkを使います
これは私がすべての勧告から好むものです:
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"}'
特定の列を任意の区切り文字で印刷する必要がある場合
awk '{print $3 " " $4}'
コル#3コル#4
awk '{print $3 "anything" $4}'
col#3anythingcol#4
そのため、列に空白がある場合は2列になりますが、任意の区切り文字で接続してもしなくてもかまいません。
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
これはあなたがBashを使っていて、あなたが捨てたい要素と同じ数の 'x'を使うことができ、それらがエスケープされていなければ無視します。
while read x b; do echo "$b"; done < filename
この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
の方法です。
Perl:
@m=`ls -ltr dir | grep ^d | awk '{print \$6,\$7,\$8,\$9}'`;
foreach $i (@m)
{
print "$i\n";
}
あなたが切り落とさない部分の行を再フォーマットしたくない場合は、私が考えることができる最善の解決策は私の答えで書かれています:
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を含むファイル/ストリームでのみ失敗します。
私は提案された答えを、場合によっては数個の空白で区切られている状況に拡張したい - OPがcut
name__を使用していない理由。
私はOPがawk
name__について尋ねたことを知っていますが、sed
name__アプローチはここでうまくいくでしょう(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:tr
name__は、 -s
オプションで の連続した文字を圧縮するためにも使用できます。
tr -s [:blank:] <somefile | cut -d' ' -f5-