1

スペース区切りの入力テキスト ファイルがあります。sed または awk を使用して、列ヘッダーがサイズである列を削除したいと思います。

入力ファイル:

id quantity colour shape size colour shape size colour shape size
1 10 blue square 10 red triangle 8 pink circle 3
2 12 yellow pentagon 3 orange rectangle 9 purple oval 6

望ましい出力:

id quantity colour shape colour shape colour shape
1 10 blue square red triangle pink circle
2 12 yellow pentagon orange rectangle purple oval
4

5 に答える 5

6

awk command

awk '
NR==1{
    for(i=1;i<=NF;i++)
        if($i!="size")
            cols[i]
}
{
    for(i=1;i<=NF;i++)
        if(i in cols)
            printf "%s ",$i
    printf "\n"
}' input > output

pretty printing

column -t -s ' ' output 

result

id  quantity  colour  shape     colour  shape      colour  shape
1   10        blue    square    red     triangle   pink    circle
2   12        yellow  pentagon  orange  rectangle  purple  oval
于 2012-07-19T10:29:49.937 に答える
3

を使用した一般的なソリューション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

そして結果は同じになります。

于 2012-07-18T12:00:36.000 に答える
1

使用cut:

$ cut -d' ' -f1-4,6,7,9,10 < in.txt   
id quantity colour shape colour shape colour shape
1 10 blue square red triangle pink circle
2 12 yellow pentagon orange rectangle purple oval
于 2012-07-19T10:25:15.780 に答える
0

固定ファイル形式の場合:

cut -f 1-4,6-7,9-10 infile
于 2012-07-18T11:16:17.347 に答える