を使用した一般的なソリューションawk
。ブロックには、削除するフィールドの位置を示すハードコーディングされた変数 ( columns_to_delete
) があります。BEGIN
次に、スクリプトは各フィールドの幅を計算し、変数の位置に一致するものを削除します。
infile
が質問の内容と次の内容を持っていると仮定しますscript.awk
:
BEGIN {
## Hard-coded positions of fields to delete. Separate them with spaces.
columns_to_delete = "5 8 11"
## Save positions in an array to handle it better.
split( columns_to_delete, arr_columns )
}
## Process header.
FNR == 1 {
## Split header with a space followed by any non-space character.
split( $0, h, /([[:space:]])([^[:space:]])/, seps )
## Use FIELDWIDTHS to handle fixed format of data. Set that variable with
## length of each field, taking into account spaces.
for ( i = 1; i <= length( h ); i++ ) {
len = length( h[i] seps[i] )
FIELDWIDTHS = FIELDWIDTHS " " (i == 1 ? --len : i == length( h ) ? ++len : len)
}
## Re-calculate fields with new FIELDWIDTHS variable.
$0 = $0
}
## Process header too, and every line with data.
{
## Flag to know if 'p'rint to output a field.
p = 1
## Go throught all fields, if found in the array of columns to delete, reset
## the 'print' flag.
for ( i = 1; i <= NF; i++ ) {
for ( j = 1; j <= length( arr_columns ); j++ ) {
if ( i == arr_columns[j] ) {
p = 0
break
}
}
## Check 'print' flag and print if set.
if ( p ) {
printf "%s", $i
}
else {
printf " "
}
p = 1
}
printf "\n"
}
次のように実行します。
awk -f script.awk infile
次の出力で:
id quantity colour shape colour shape colour shape
1 10 blue square red triangle pink circle
2 12 yellow pentagon orange rectangle purple oval
EDIT :ああ、ちょうど今、2 つのフィールド間の結合のため、出力が正しくないことに気付きました。処理を開始する前にすべての行の最大列サイズを確認する必要があるため、作業が多すぎる問題を修正します。しかし、このスクリプトで、アイデアが得られることを願っています。今は時間がないので、後で修正できるかもしれませんが、よくわかりません。
編集 2 : 削除された各フィールドに追加のスペースを追加するのを修正しました。思ったより簡単でした:-)
編集 3 : コメントを参照してください。
BEGIN
追加の変数が引数として提供されていることを確認するようにブロックを変更しました。
BEGIN {
## Check if a variable 'delete_col' has been provided as argument.
if ( ! delete_col ) {
printf "%s\n", "Usage: awk -v delete_col=\"column_name\" -f script.awk " ARGV[1]
exit 0
}
}
そしてFNR == 1
、削除する列の数を計算するプロセスをパターン化するために追加されました。
## Process header.
FNR == 1 {
## Find column position to delete given the name provided as argument.
for ( i = 1; i <= NF; i++ ) {
if ( $i == delete_col ) {
columns_to_delete = columns_to_delete " " i
}
}
## Save positions in an array to handle it better.
split( columns_to_delete, arr_columns )
## ...
## No modifications from here until the end. Same code as in the original script.
## ...
}
次のように実行します。
awk -v delete_col="size" -f script.awk infile
そして結果は同じになります。