一重引用符のエスケープの問題の場合、合理的な回避策は引用符を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コプロセスを使用する必要があります...そしてそれは面倒な価値がありません。