一重引用符のエスケープの問題の場合、合理的な回避策は引用符を2倍にすることである可能性があるため、次を使用します。
`sed "s/'/''/g" < "$f"`
の代わりにファイルの内容を含めるには、ファイル名を使用するつもりであると思われる場所でcat
の2回目の呼び出しには、次を使用します。LIKE
${f/"'"/"''"/}
$f
を実行する代わりにリテラル文字列の内容を含め、引用符を2倍にします。${varname/match/replace}
式は構文であり、bash
すべてのシェルで機能するとは限りません。使用する:
`echo "$f" | sed "s/'/''/g"`
他のシェルについて心配する必要がある場合。
そのSQLには他にもたくさんの問題があります。
- 2回目の呼び出しで実行 しようとしています。
$f
あなたがそれを意図していなかったと私はかなり確信しています。リテラル文字列を含めるつもりだったと思います。
- サブクエリも間違っています。括弧がありません。
(SELECT ...)
だけではありませんSELECT
。
- あなたの
LIKE
表現もおそらくあなたが意図したことをしていないでしょう。SQLワイルドカードなので、おそらく%
の代わりに意味します。*
%
また、バッククォートを$()
(IMOがより明確で読みやすいため)に変更し、サブクエリ構文を修正し、列を明確にするためにエイリアスを追加し、代わりにヒアドキュメントを使用してpsql
's stdinに渡すと、結果は次のようになります。
psql $dbname $username <<__END__
UPDATE entries
SET content=$(sed "s/'/''/g" < "$f")
WHERE id=(SELECT e.id FROM entries e WHERE e.path LIKE '$(echo "$f" | sed "s/'/''/g")');
__END__
上記は、かなり最新のPostgreSQLを使用していることを前提としていますstandard_conforming_strings = on
。そうでない場合は、正規表現を変更して、アポストロフィを2倍にするのではなく、アポストロフィをエスケープし\
、文字列の前に。を付けるとE
、にO'Brien
なりE'O\'Brien'
ます。最近のPostgreSQLでは、代わりにになり'O''Brien'
ます。
一般に、データベースのスクリプトの問題を解決するには、DBD::Pgを使用したPerlやpsycopgを使用したPythonなどの実際のスクリプト言語を使用することをお勧めします。シェルでの作業は少しファンキーです。この式は、パラメーター化されたステートメントをサポートするデータベースインターフェイスを使用して作成する方がはるかに簡単です。
たとえば、私はこれを次のように書きます:
import os
import sys
import psycopg2
try:
connstr = sys.argv[1]
filename = sys.argv[2]
except IndexError as ex:
print("Usage: %s connect_string filename" % sys.argv[0])
print("Eg: %s \"dbname=test user=fred\" \"some_file\"" % sys.argv[0])
sys.exit(1)
def load_file(connstr,filename):
conn = psycopg2.connect(connstr)
curs = conn.cursor()
curs.execute("""
UPDATE entries
SET content = %s
WHERE id = (SELECT e.id FROM entries e WHERE e.path LIKE '%%'||%s);
""", (filename, open(filename,"rb").read()))
curs.close()
if __name__ == '__main__':
load_file(connstr,filename)
SQLワイルドカード%
はエスケープするために2倍になっているため%
、最終的なSQLでは1になります。これは、Pythonが%
フォーマット指定子として使用しているため、リテラル%
をエスケープするには2倍にする必要があるためです。
上記のスクリプトを簡単に変更して、ファイル名のリストを受け入れ、データベースに1回接続して、すべてのファイル名のリストをループすることができます。これは、特にすべてを1つのトランザクションで実行する場合は、はるかに高速になります。psql
スクリプトでそれを行うのは本当に苦痛です。ここに示すように、bashコプロセスを使用する必要があります...そしてそれは面倒な価値がありません。