この行は、2番目のフィールドに空白ができるまで機能しました。
svn status | grep '\!' | gawk '{print $2;}' > removedProjs
awkにすべてを$ 2以上で印刷させる方法はありますか?($ 3、$ 4 ..列がなくなるまで?)
Cygwinを使用するWindows環境でこれを実行していることを追加する必要があると思います。
svn status | grep '\!' | cut -d' ' -f2- > removedProjs
この行は、2番目のフィールドに空白ができるまで機能しました。
svn status | grep '\!' | gawk '{print $2;}' > removedProjs
awkにすべてを$ 2以上で印刷させる方法はありますか?($ 3、$ 4 ..列がなくなるまで?)
Cygwinを使用するWindows環境でこれを実行していることを追加する必要があると思います。
svn status | grep '\!' | cut -d' ' -f2- > removedProjs
回答:
最初の列を除くすべてを出力します:
awk '{$1=""; print $0}' somefile
最初の2列を除くすべてを印刷します。
awk '{$1=$2=""; print $0}' somefile
awk '{$1=""; print substr($0,2)}' input_filename > output_filename
awk -F, -vOFS=, '{$1=""; print $0}'
最終的には、最初の区切り文字($1
空の文字列として含まれます)になります。あなたはストリップできることとsed
いえ:awk -F, -vOFS=, '{$1=""; print $0}' | sed 's/^,//'
カットを使用してより簡単な答えを持つ重複した質問があります:
svn status | grep '\!' | cut -d\ -f2-
-d
区切り文字(スペース)を-f
指定し、列のリストを指定します(すべて2番目から始まる)。
awk
バージョン、ラインバッファリングの問題がであるcut
これ、awk
:ありませんstackoverflow.com/questions/14360640/...を
awk
。隣接する複数のスペース文字を扱います。単一のセパレータとしてcut
。また、これは当面の問題ではありませんがcut
、単一のリテラル文字のみを受け入れます。区切り文字として、awk
正規表現を許可します。
forループを使用して、$ 2から$ NF(行のフィールド数を表す組み込み変数)までの印刷フィールドをループできます。
編集:「印刷」は改行を追加するので、結果をバッファリングする必要があります。
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"}'
'{for(i=11;i<=NF-1;i++){printf "%s ", $i}; print $NF;}'
先頭または末尾にスペースはありません。
awk '{out=$2; for(i=3;i<=NF;i++){out=out" "$i}; print out}'
私の答えはVeeArrの1つに基づいていますが、2列目(および残りの列)を印刷する前に空白で始まっていることに気付きました。私は評判ポイントが1つしかないので、コメントすることはできません。そのため、これは新しい答えになります。
2番目の列が「out」で始まり、他のすべての列(存在する場合)を追加します。これは、2番目の列がある限りうまくいきます。
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の値を使用します(変更される可能性があります)。
より移植性がある、とOFSへのFSの変化をトリガしません:
注:^[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
以下のようにgensub
、GNU awk の関数を使用して、余分な(先頭または末尾の)空白を追加せず、既存の空白を保持するソリューションを構築することはかなり可能です。
$ 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
カウントを指定してフィールドのグループを交換するために使用することもできます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]*
入力行で先行スペースを許可するために使用されます。
私は個人的に上記のすべての答えを試しましたが、それらのほとんどは少し複雑であるか、正しくありませんでした。私の観点からそれを行う最も簡単な方法は次のとおりです。
awk -F" " '{ for (i=4; i<=NF; i++) print $i }'
ここで、-F ""は、awkが使用する区切り文字を定義します。私の場合は空白です。これはawkのデフォルトの区切り文字でもあります。つまり、-F ""は無視できます。
ここで、NFはフィールド/列の総数を定義します。したがって、ループは4番目のフィールドから最後のフィールド/列まで始まります。
$ NはN番目のフィールドの値を取得します。したがって、print $ iはループカウントに基づいて現在のフィールド/列を印刷します。
これは私をとても苛立たせました、私は座って、cut
GNU Awk 3.1.7でテストされたようなフィールド仕様パーサーを書きました。
まず、と呼ばれる新しいAwkのライブラリスクリプトを作成するpfcut
などして、
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);
}
cut
ないようですawk
#2から始まる列を出力します(出力の先頭に末尾のスペースはありません)。
ls -l | awk '{sub(/[^ ]+ /, ""); print $0}'
+
フィールドawk
は複数のスペースで区切られている可能性があるため、スペースの後に追加する必要があります(隣接する複数のスペースを単一のセパレーターとして扱います)。また、awk
先頭のスペースは無視されるため、正規表現はで始める必要があり^[ ]*
ます。スペースをセパレータとして使用すると、ソリューションを一般化することもできます。たとえば、次の例では、3番目のフィールドからすべてが返されawk '{sub(/^[ ]*([^ ]+ +){2}/, ""); print $0}'
ます。
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
行の一部を切り取らないで再フォーマットしたくない場合、私が考えることができる最良の解決策は私の答えに書かれています:
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を含むファイル/ストリームでのみ失敗します。
これは、Bashを使用していて、破棄したい要素と同じ数の「x」を使用でき、エスケープされていない場合は複数のスペースを無視する場合に機能します。
while read x b; do echo "$b"; done < filename
Perl:
@m=`ls -ltr dir | grep ^d | awk '{print \$6,\$7,\$8,\$9}'`;
foreach $i (@m)
{
print "$i\n";
}
このawk
関数は$0
、begin
〜のフィールドを含むの部分文字列を返しますend
。
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);
そのセクションを取得$0
するには、フィールド3〜5をカバーします。
middle = fields(3, 5);
b, e, p, i
関数パラメーターリストのawk
意味がないのは、ローカル変数を宣言する方法にすぎません。
提案された回答を、フィールドが複数の空白で区切られている可能性がある状況に拡張したいcut
と思います。これは、OPが使用されていない理由だと思います。
OPがについて尋ねたことは知ってawk
いますが、sed
ここではアプローチが機能します(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およびcut:
オプションをtr
使用して、連続する文字をスクイーズするためにも使用でき-s
ます。
tr -s [:blank:] <somefile | cut -d' ' -f5-
Awkの例はここでは複雑に見えますが、これは単純なBashシェル構文です。
command | while read -a cols; do echo ${cols[@]:1}; done
どこに1
あなたのであるnが 0から列目のカウント。
このファイルのコンテンツ(in.txt
)を考えると:
c1
c1 c2
c1 c2 c3
c1 c2 c3 c4
c1 c2 c3 c4 c5
ここに出力があります:
$ while read -a cols; do echo ${cols[@]:1}; done < in.txt
c2
c2 c3
c2 c3 c4
c2 c3 c4 c5
awk
最初の数列を抽出してから残りを印刷したかったので、ここに示した解決策のいずれにも満足していなかったため、perl
代わりに変更しました。次のコードは、最初の2つの列を抽出し、残りをそのまま表示します。
echo -e "a b c d\te\t\tf g" | \
perl -ne 'my @f = split /\s+/, $_, 3; printf "first: %s second: %s rest: %s", @f;'
Chris Koknatのperl
ソリューションと比較した場合の利点は、実際には最初のn個の要素のみが入力文字列から分割されることです。文字列の残りの部分はまったく分割されないため、完全にそのまま残ります。私の例では、スペースとタブを組み合わせてこれを示しています。
抽出する列の数を変更するに3
は、例のをn + 1 に置き換えます。
ls -la | awk '{o=$1" "$3; for (i=5; i<=NF; i++) o=o" "$i; print o }'
この答えから悪くはありませんが、自然な間隔がなくなっています。
次に、これと比較してください。
ls -la | cut -d\ -f4-
次に、違いがわかります。
でもls -la | awk '{$1=$2=""; print}'
に基づいている答えは、これまでに書式を保持されていない最高の投票しました。
したがって、私は以下を使用し、最初に明示的な選択列も許可します。
ls -la | cut -d\ -f1,4-
すべてのスペースも列にカウントされることに注意してください。たとえば、以下では、列1と3は空で、2はINFO、4は次のようになります。
$ echo " INFO 2014-10-11 10:16:19 main " | cut -d\ -f1,3
$ echo " INFO 2014-10-11 10:16:19 main " | cut -d\ -f2,4
INFO 2014-10-11
$
フォーマットされたテキストが必要な場合は、コマンドをエコーでチェーンし、$ 0を使用して最後のフィールドを出力します。
例:
for i in {8..11}; do
s1="$i"
s2="str$i"
s3="str with spaces $i"
echo -n "$s1 $s2" | awk '{printf "|%3d|%6s",$1,$2}'
echo -en "$s3" | awk '{printf "|%-19s|\n", $0}'
done
プリント:
| 8| str8|str with spaces 8 |
| 9| str9|str with spaces 9 |
| 10| str10|str with spaces 10 |
| 11| str11|str with spaces 11 |
340票の間違った最も支持されたanwserのため、私はちょうど私の人生の5分を失いました!これを賛成する前に誰かがこの答えを試しましたか?ありません。まったく役に立たない。
$ 5の後にIPアドレスを入力すると、テキストが増える場合とない場合があります。$ 5より後のものがあれば、IPアドレスから行末まですべてが必要です。私の場合、これは実際にはawkプログラムではなくawkワンライナーなので、awkが問題を解決する必要があります。最も投票されたが完全に間違った答えを使用して最初の4つのフィールドを削除しようとすると:
echo " 7 27.10.16. Thu 11:57:18 37.244.182.218" | awk '{$1=$2=$3=$4=""; printf "[%s]\n", $0}'
それは間違って役に立たない応答を吐き出します(私は[..]を追加して説明します)
[ 37.244.182.218 one two three]
substrとこの間違った答えを組み合わせるいくつかの提案もあります。そのような複雑さは改善です。
代わりに、カットポイントとawkが必要になるまで列の幅が固定されている場合、正しい答えは次のとおりです。
echo " 7 27.10.16. Thu 11:57:18 37.244.182.218" | awk '{printf "[%s]\n", substr($0,28)}'
これにより、必要な出力が生成されます。
[37.244.182.218 one two three]
grep | awk
アンチパターンである -あなたがしたいawk '/!/ { print $2 }'