面倒すぎる:
awk '{print " "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11" "$12" "$13}' things
余分な先頭または末尾を追加しないソリューション 空白 :
awk '{ for(i=4; i<NF; i++) printf "%s",$i OFS; if(NF) printf "%s",$NF; printf ORS}'
### Example ###
$ echo '1 2 3 4 5 6 7' |
awk '{for(i=4;i<NF;i++)printf"%s",$i OFS;if(NF)printf"%s",$NF;printf ORS}' |
tr ' ' '-'
4-5-6-7
Sudo_O は、三項演算子を使用したエレガントな改善を提案しますNF?ORS:OFS
$ echo '1 2 3 4 5 6 7' |
awk '{ for(i=4; i<=NF; i++) printf "%s",$i (i==NF?ORS:OFS) }' |
tr ' ' '-'
4-5-6-7
EdMorton は、フィールド間の元の空白を保持するソリューションを提供します。
$ echo '1 2 3 4 5 6 7' |
awk '{ sub(/([^ ]+ +){3}/,"") }1' |
tr ' ' '-'
4---5----6-7
BinaryZebra は、2つの素晴らしいソリューションも提供します。
(これらのソリューションは、元の文字列の末尾のスペースも保持します)
$ echo -e ' 1 2\t \t3 4 5 6 7 \t 8\t ' |
awk -v n=3 '{ for ( i=1; i<=n; i++) { sub("^["FS"]*[^"FS"]+["FS"]+","",$0);} } 1 ' |
sed 's/ /./g;s/\t/->/g;s/^/"/;s/$/"/'
"4...5...6.7.->.8->."
$ echo -e ' 1 2\t \t3 4 5 6 7 \t 8\t ' |
awk -v n=3 '{ print gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1); }' |
sed 's/ /./g;s/\t/->/g;s/^/"/;s/$/"/'
"4...5...6.7.->.8->."
コメントの larsr で与えられる解決策はほぼ正しいです:
$ echo '1 2 3 4 5 6 7' |
awk '{for (i=3;i<=NF;i++) $(i-2)=$i; NF=NF-2; print $0}' | tr ' ' '-'
3-4-5-6-7
これは larsr ソリューションの修正されパラメータ化されたバージョンです。
$ echo '1 2 3 4 5 6 7' |
awk '{for(i=n;i<=NF;i++)$(i-(n-1))=$i;NF=NF-(n-1);print $0}' n=4 | tr ' ' '-'
4-5-6-7
2013年9月以前のその他の回答はすべて素晴らしいですが、スペースを追加します。
余分な先行スペースの追加に答える の例:
$ echo '1 2 3 4 5 6 7' |
awk '{$1=$2=$3=""}1' |
tr ' ' '-'
---4-5-6-7
$ echo '1 2 3 4 5 6 7' |
awk '{for(i=4;i<=13;i++)printf "%s ",$i;printf "\n"}' |
tr ' ' '-'
4-5-6-7-------
awk '{for(i=1;i<4;i++) $i="";print}' file
使用カット
$ cut -f4-13 file
または、awkを主張し、$ 13が最後のフィールドである場合
$ awk '{$1=$2=$3="";print}' file
else
$ awk '{for(i=4;i<=13;i++)printf "%s ",$i;printf "\n"}' file
これを試して:
awk '{ $1=""; $2=""; $3=""; print $0 }'
これを行う正しい方法は、RE間隔を使用することです。これにより、スキップするフィールドの数を単純に指定でき、残りのフィールドのフィールド間スペースを保持します。
例えばこの質問で議論していると思われる入力の形式が与えられた場合、残りのフィールド間の間隔に影響を与えずに最初の3つのフィールドをスキップするには、次のようにします。
$ echo '1 2 3 4 5 6' |
awk '{sub(/([^ ]+ +){3}/,"")}1'
4 5 6
先頭のスペースと空白以外のスペースに対応したいが、デフォルトのFSを使用する場合は、次のようになります。
$ echo ' 1 2 3 4 5 6' |
awk '{sub(/[[:space:]]*([^[:space:]]+[[:space:]]+){3}/,"")}1'
4 5 6
文字セットで否定できないREであるFSがある場合は、最初に単一の文字に変換できます(RSはフィールド内に表示できないため、単一の文字である場合はRSが理想的です) 、それ以外の場合はSUBSEPを検討してください)、RE間隔の置換を適用してから、OFSに変換します。例えば「。」のチェーンがフィールドを区切る場合:
$ echo '1...2.3.4...5....6' |
awk -F'[.]+' '{gsub(FS,RS);sub("([^"RS"]+["RS"]+){3}","");gsub(RS,OFS)}1'
4 5 6
OFSが単一の文字であり、入力フィールドに表示できない場合は、次のように減らすことができます。
$ echo '1...2.3.4...5....6' |
awk -F'[.]+' '{gsub(FS,OFS); sub("([^"OFS"]+["OFS"]+){3}","")}1'
4 5 6
次に、フィールドを再割り当てするすべてのループベースのソリューションと同じ問題があります-FSはOFSに変換されます。それが問題になる場合は、GNU awksのpatsplit()関数を調べる必要があります。
現在、ほとんどすべての回答が先頭のスペース、末尾のスペース、またはその他のセパレーターの問題を追加しています。区切り記号が空白で、出力区切り記号がawk
を使用する単一のスペースである4番目のフィールドから選択するには、次のようになります。
awk '{for(i=4;i<=NF;i++)printf "%s",$i (i==NF?ORS:OFS)}' file
開始フィールドをパラメーター化するには、次のようにします。
awk '{for(i=n;i<=NF;i++)printf "%s",$i (i==NF?ORS:OFS)}' n=4 file
また、終了フィールド:
awk '{for(i=n;i<=m=(m>NF?NF:m);i++)printf "%s",$i (i==m?ORS:OFS)}' n=4 m=10 file
awk '{$1=$2=$3="";$0=$0;$1=$1}1'
入力
1 2 3 4 5 6 7
出力
4 5 6 7
echo 1 2 3 4 5| awk '{ for (i=3; i<=NF; i++) print $i }'
オプション1〜3には、複数の空白に関する問題があります(ただし、単純です)。これが、オプション4と5を開発する理由です。オプション4と5は、複数の空白を問題なく処理します。もちろん、n=0
でオプション4または5を使用すると、n=0
は分割しないことを意味するため、両方とも先頭の空白を保持します。
シンプルなカットソリューション(単一の区切り文字で動作):
$ echo '1 2 3 4 5 6 7 8' | cut -d' ' -f4-
4 5 6 7 8
Awkの再計算を強制すると、追加された先行スペースの問題(awkの一部のバージョンで機能する)が解決される場合があります。
$ echo '1 2 3 4 5 6 7 8' | awk '{ $1=$2=$3="";$0=$0;} NF=NF'
4 5 6 7 8
printf
でフォーマットされた各フィールドを印刷すると、より詳細に制御できます。
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ for (i=n+1; i<=NF; i++){printf("%s%s",$i,i==NF?RS:OFS);} }'
4 5 6 7 8
ただし、以前の回答はすべて、フィールド間のすべてのFSをOFSに変更します。それに対するいくつかのソリューションを構築しましょう。
フィールドと区切り文字を削除するsubを含むループはより移植性が高く、FSからOFSへの変更をトリガーしません。
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ for(i=1;i<=n;i++) { sub("^["FS"]*[^"FS"]+["FS"]+","",$0);} } 1 '
4 5 6 7 8
注: "^ [" FS "] *"は、先頭にスペースを含む入力を受け入れます。
次のように、余分な先頭または末尾の空白を追加しないソリューションを構築し、GNU awkの関数gensub
を使用して既存の空白を保持することは非常に可能です。
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ print gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1); }'
4 5 6 7 8
カウントn
が指定されたフィールドリストをスワップするためにも使用できます。
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ a=gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1);
b=gensub("^(.*)("a")","\\1",1);
print "|"a"|","!"b"!";
}'
|4 5 6 7 8 | ! 1 2 3 !
もちろん、このような場合、行の両方の部分を分離するためにOFSが使用され、フィールドの末尾の空白は引き続き印刷されます。
注1:["FS"]*
は、入力行の先頭スペースを許可するために使用されます。
私は誰もプレーンシェルを提供したとは信じられません:
while read -r a b c d; do echo "$d"; done < file
Printステートメントの使用を避ける別の方法:
$ awk '{$1=$2=$3=""}sub("^"FS"*","")' file
Awkでは、条件がtrueの場合、印刷がデフォルトのアクションです。
先頭または末尾の空白を追加しないPerlソリューション:
Perl -lane 'splice @F,0,3; print join " ",@F' file
Perlの@F
自動分割配列はインデックス0
で始まり、awkフィールドは$1
で始まります
カンマ区切りデータのPerlソリューション:
Perl -F, -lane 'splice @F,0,3; print join ",",@F' file
Pythonソリューション:
python -c "import sys;[sys.stdout.write(' '.join(line.split()[3:]) + '\n') for line in sys.stdin]" < file
Cutには--complementフラグがあり、列を簡単に(そして高速に)削除できます。結果の構文は、あなたがやりたいことと似ています-ソリューションを読みやすく/理解しやすくします。補完は、連続していない列を削除する場合にも機能します。
$ foo='1 2 3 %s 5 6 7'
$ echo "$foo" | cut --complement -d' ' -f1-3
%s 5 6 7
$
私はこの他の可能性を見つけました、多分それはまた有用かもしれません...
awk 'BEGIN {OFS=ORS="\t" }; {for(i=1; i<14; i++) print $i " "; print $NF "\n" }' your_file
注: 1.表形式データおよび列$ 1から$ 14の場合
私は最初に非常に支持されたが間違った答えに悩まされたので、そこで答えを書くのに十分であることがわかりました。答えをそれほど複雑にする理由がわからないので、提案された解決策は好きではありません。
私はログを持っていますが、IPアドレスが$ 5を超えると、テキストが増えたり、テキストがなくなったりします。 $ 5以降に何かがある場合、IPアドレスから行末までのすべてが必要です。私の場合、これは実際にはawkプログラムではなく、awk onelinerではないため、awkは問題を解決する必要があります。古い見栄えがよく、最も支持されているが完全に間違った答えを使用して最初の4つのフィールドを削除しようとすると:
echo " 7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{$1=$2=$3=$4=""; printf "[%s]\n", $0}'
それは間違った役に立たない応答を吐き出します(実証するために[]を追加しました):
[ 37.244.182.218 one two three]
代わりに、カットポイントとawkが必要になるまで列の幅が固定されている場合、正しい簡単な答えは次のとおりです。
echo " 7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{printf "[%s]\n", substr($0,28)}'
これにより、目的の出力が生成されます。
[37.244.182.218 one two three]
私にとって、この要求に対する最もコンパクトで準拠したソリューションは
$ a='1 2\t \t3 4 5 6 7 \t 8\t ';
$ echo -e "$a" | awk -v n=3 '{while (i<n) {i++; sub($1 FS"*", "")}; print $0}'
インスタンスファイルfoo.txtのように処理する行がさらにある場合は、iを0にリセットすることを忘れないでください:
$ awk -v n=3 '{i=0; while (i<n) {i++; sub($1 FS"*", "")}; print $0}' foo.txt
フォーラムに感謝します。
カットを使用:
cut -d <The character between characters> -f <number of first column>,<number of last column> <file name>
例:file1
を含む場合:car.is.Nice.equal.bmw
実行:cut -d . -f1,3 file1
はcar.is.Nice
を出力します