Bashスクリプト内でsedコマンドラインパラメータと変数を使用する

Bashスクリプト内でsedコマンドラインパラメータと変数を使用する

複数のコマンドライン引数を必要とするbashスクリプトがあります。この場合、重要なのはテキストファイルである最初の$ 1です。

ヘッダーはかなり長いです。以下はいくつかのフィールドの例です。

COL0___LINE_NUMBER
COL1_AFF_ID
COL2_FULL_NAME
COL3_ADDRESS
BDID
BEST_STATE
COL48_LATITUDE   
COL49_LONGITUDE

ヘッダー行を変更する必要がありますが、次のコードを使用してこれを行うことができます。これはまさに私が望むことをしますが、これがbashスクリプトを最初に書くことであると考えると、以下の出力の変数を保持するスタイルの変更などを歓迎します。

columns=`cat $1 | head -1 |sed 's/-/_/g' |  sed 's/ /_/g' |
    sed 's/COL[0-9]\+_BDID/DROP_BDID/g' | sed 's/COL[0-9]\+_//g' |
    tr '\t' '\n' | tr  "[:lower:]" "[:upper:]"`

注:改行を含むタブ形式は、純粋に列見出しを反映する際の審美的な側面を考慮したものです。これは私自身の読みやすさと vertica create table ステートメントをエコーするスクリプトユーザーの読みやすさのためです。

とにかく、スクリプトで新しいバージョンを使用できるように、列変数をテキストファイルのヘッダー行にしたいと思います。だから私は完全な生のテキストファイルが欲しいいいえこれは元のヘッダー行であり、私が作成したものなので、以下は私のファイルの編集されたバージョンを表します。

col_arr=($columns)
cut_cols = ""

for i in ${!col_arr[@]}; do
    if [[ "${col_arr[$i]}" =~ ^(__LINE_NUMBER|CONFIDENCE|DROP_BDID|LINE_NUMBER|ZIP9|ZIP9|ZIP9MATCH)$ ]]; then
            echo "$i"
            #haven't written yet, but this will add to cut_cols so that 
            #I can remove the above listed columns in the text file 
            #based on their index.
    fi
done
/opt/vertica/bin/vsql -U ${4} -w ${5} -h ${database} \
    -c "copy $schema.$table from STDIN delimiter E'\t' direct no escape;"

ベストアンサー1

元のシェルパイプラインのすべてのコマンドをcolumns=単一のsedスクリプトにまとめることができます。スクリプトsedは入力の最初の行のみを変更してから終了します。次のアプローチは正確にcolumns=元の質問と同じです。

columns=$(
    sed '               
        1 {                                   # execute block on line 1
            s/-/_/g     
            s/ /_/g     
            s/COL[0-9]\+_BDID/DROP_BDID/g
            s/COL[0-9]\+_//g
            s/\t/\n/g   
            y/abcdefghijklmnopqrstuv/ABCDEFGHIJKLMNOPQRSTUV/
            q                                 # quit after line 1
        }
    ' "$1"
)

# . . .

私は読みやすくするために複数行形式を好みます。もともと文は一行にすぎませんが、はるかに効率が悪く、読みにくいと思います。ヨムド

これで、newlinesで区切られた変数に格納されている入力ファイル(arg 1)のヘッダーがありますcolumns$columnsループを使用して文字列を繰り返すと、列for名は改行文字で区切られますcut_cols

cut_cols="$(
    for col in $columns
    do
        case $col in
        (*__LINE_NUMBER*|*CONFIDENCE*|*DROP_BDID*|*LINE_NUMBER*|*ZIP9*|*ZIP9MATCH*)
                echo "$col"
                ;;
        esac
    done
)"

好みに応じて同じことを行います。

cut_cols=
for col in $columns
do
    case $col in
        (*__LINE_NUMBER*|*CONFIDENCE*|*DROP_BDID*|*LINE_NUMBER*|*ZIP9*|*ZIP9MATCH*)
            cut_cols="$cut_cols $col"
            ;;
    esac
done
cut_cols=$(echo "$cut_cols" | sed 's/^ *//; s/ /\n/g')

cut_cols私はシェル配列を使用していないので、配列ループをテストしていません。上記の反復方法は$columns比較的一般的で伝統的な方法である。 Arraysは拡張であり、すべてのシェルで使用できるわけではありません。

に割り当てた後cut_colsは同じことを繰り返すことができます$columns

元のファイルデータを含む新しいヘッダーを送信するには、新しいヘッダーを印刷してから、元のファイルの最初の行を除いてすべて印刷します。 2つのコマンドの出力を1つのプログラムのように一緒にリダイレクトできるように、コマンドグループ(および{間)でこれを行います。}

以下は、元のヘッダー行なしで完全な生のテキストファイルを生成しますが、生成したヘッダー行を含む次のようstdinに送信しますvsql

# . . .

{                                   # start command group

    echo "$columns" | tr '\n' '\t'; # print with tabs instead of newlines
    echo                            # add newline record separator
    sed 1d "$1"                     # print all but 1st line of "$1"

} |                                 # pipe as one file to vsql

/opt/vertica/bin/vsql -U ${4} -w ${5} -h ${database} \
    -c "copy $schema.$table from STDIN delimiter E'\t' direct no escape;"

おすすめ記事