在 sed 內部 Bash 腳本中使用命令行參數和變數
我有一個 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;"
我們可以將原始
columns=
shell 管道中的所有命令組合到一個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" ) # . . .
為了便於閱讀,我更喜歡多行格式。儘管最初的聲明是一行,但效率要低得多,而且在我看來,更難閱讀。yomd
現在您已經從輸入文件 (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
因為我不使用 shell 數組。上面的迭代方法$columns
是比較通用和傳統的方法。Array
s 是一個擴展,並非在每個 shell 中都可用。分配給 之後
cut_cols
,您可以像 一樣對其進行迭代$columns
。要發送帶有原始文件數據的新標題,請列印新標題,然後列印除原始文件第一行之外的所有內容。在命令組(介於
{
和之間}
)中執行此操作,這樣您就可以將兩個命令的輸出重定向到一起,就好像它們是一個程序一樣。以下生成完整的原始文本文件,沒有原始標題行,並使用您創建的文件,並將其發送到
stdin
ofvsql
:# . . . { # 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;"