web-dev-qa-db-ja.com

ファイル内の値を置き換える

私はファイルを持っています:

$cat file1.txt
1234|W
1345|S
8427|D
2132|C
3243|V

そして私のSQLファイルは:

$cat select.sql
SELECT *
  FROM CUSTOMERS
 WHERE ID IN (FLAG);

そして私は次の指示でシェルを持っています

$cat replace.ksh
!#/bin/ksh

S_ids=`awk -F"|" '{print "\47" $1 "\47" ","}' file1.txt |sed '$s/,$//'`

sed -i "s/FLAG/${S_ids}/g" select.sql

変数「S_ids」の値をWordFLAGのファイルselect.sql入力に入れる必要がありました。結果は次のようにする必要があります。

$cat select.sql
SELECT *
  FROM CUSTOMERS
 WHERE ID IN ('1234',
'1345',
'8427',
'2132',
'3243');

sed -i "s/FLAG/${S_ids}/g" select.sqlを試しましたが、期待した結果が得られませんでした。

3
Miguel Angel

これが機能しない理由は、エラーメッセージ(提供するために省略した)から推測できます。

sed: -e expression #1, char 14: unterminated `s' command

sedコマンドは、複数行の値を受け入れません。複数の行を1つの行に折りたたむ必要があります。次のようなスクリプトを使用してこれを行うことができます。

#!/bin/ksh
S_ids="'$(cut -d'|' -f1 file1.txt | tr '\n' ' ' | sed -e 's/ *$//' -e "s/ /','/g")'"
sed -i "s/FLAG/${S_ids}/g" select.sql

どのようにS_idsが生成され、パイプラインの各部分を取得できます

cut -d'|' -f1 file.txt        # Extract first column
tr '\n' ' '                   # Convert newlines to spaces
sed -e 's/ *$//'              # Strip the trailing space
sed -e "s/ /','/g"            # Replace each remaining space with the three characters ','
2
roaima
_#! /bin/ksh

inputfile='file1.txt'
sqlfile='select.sql'

S_ids=$(awk -F"|" '{gsub(/^|$/,"\\'\''",$1) ; print $1","}' "$inputfile" | 
        xargs | 
        sed -e 's/,$//')

sed -i "s/FLAG/${S_ids}/g" "$sqlfile"
_

出力:

_$ cat select.sql 
SELECT *
  FROM CUSTOMERS
 WHERE ID IN ('1234', '1345', '8427', '2132', '3243');
_

これは、awkgsub()関数を使用して、各行の最初のフィールドに_\'_を追加し、最後に_\',_を追加します。 _\'_だけでなく_'_を追加して、単一引用符がxargsを通るパイプを存続させるようにします。

_'\''_を使用して、単一引用符のawkスクリプト内に単一引用符を埋め込むことに注意してください-「end-single-quote、escaped-single-quote、start-single-quote-」と読みます再び"。

xargsを実行するコマンドがない場合、デフォルトは_xargs echo_になり、すべての出力行(file1.txtの単一引用符で囲まれた最初のフィールド)がスペースで区切られた1行に配置されます。これは、_file1.txt_に数万の行がない限り機能します-シェルの最大行長(通常は128KB以上)を超えるのに十分です。

最後に、xargsの出力をsedにパイプして、最後の_,_を行から削除します。

_select.sql_の各IDの後に改行を含める場合は、スクリプトの最後の行を次のように変更します。

_sed -i "s/FLAG/${S_ids}/g; s/, /\n/g" "$sqlfile"
_

出力は次のようになります。

_SELECT *
  FROM CUSTOMERS
 WHERE ID IN ('1234',
'1345',
'8427',
'2132',
'3243');
_
0
cas
$ FLAG=$(awk -F\| '{printf("%s, ", $1)}' file1.txt)
$ echo $FLAG 
1234, 1345, 8427, 2132, 3243,
$ sed "s/FLAG/${FLAG%%, }/" select.sql
SELECT *
  FROM CUSTOMERS
 WHERE ID IN (1234, 1345, 8427, 2132, 3243);

これは、フラグリストがコマンドラインに収まるほど小さいかどうかに依存します。そうでない場合は、awkでgetlineを使用してfile1.txtを処理し、置換文字列をBEGINパターンで収集してから、select.sqlを処理できます。

0
James K. Lowden