sedコマンドで変数を二重引用符で正しく囲む方法

sedコマンドで変数を二重引用符で正しく囲む方法

次の2つのデータ「列」を含む.csvファイルがあります。

test1.ts.meta,Before Sunrise (1995)
test2.ts.meta,A Beautiful Mind (2001)
test3.ts.meta,Departures (2008)
test4.ts.meta,Love & Other Drugs (2010)

このコマンドを使用して、各.ts.metaファイルの2行を対応する映画の名前に置き換えようとします。

cat 1TBMovie2_dotTSdotMeta.txt | while IFS=, read file moviename; do sed "2 s/^.*$/$moviename/" "$file"; done

ムービー名にアンパサンド(&)が含まれている点を除くと正常に機能します。
たとえば、映画のタイトルは次のとおりです。愛と薬(2010)この場合、.ts.meta ファイルの 2 行目に次のムービー名が表示されます。

Love Love Love & Other Drugs Other Drugs (2010) Other Drugs (2010)

同じ映画のタイトル:愛と思いやり(2015).ts.meta ファイルに次のように表示されます。愛愛愛とマシーマッシュ(2015)マシー(2015)

混乱した点は...という名前の映画の.ts.metaファイルを開くと愛と思いやり(2015)2行目を手動で削除し、上記のコマンドを保存してもう一度実行しました。 2行目にこの内容があります...ラブマッシュ(2015)「愛」と「慈悲」の間には2つのスペースがあります。

$file変数で行ったように、$ moviename変数を二重引用符で囲む必要がありますか? sedが&文字を特別な意味で扱うと思いますか?

問題を明確にするための追加情報は次のとおりです。

私のcsvファイル(実際にはupdatemeta.txtと呼ばれる)

test1.ts.meta,Carols from King's (2013)
test2.ts.meta,Before Sunrise (1995)
test3.ts.meta,Love & Other Drugs (2010)
test4.ts.meta,Departures (2008)

test1.ts.meta

1:0:19:1B1C:802:2:11A0000:0:0:0:
Carols from King's
The traditional Christmas carol concert from King's College Chapel, Cambridge. Stephen Cleobury conducts the famous chapel choir in carols old and new. [HD] [S]
1387969020

448066800
2913369072
f:0,c:00157c,c:01157e,c:02157f,c:03157c,c:050001
188
0

test2.ts.meta

1:0:1:189E:7FD:2:11A0000:0:0:0:
Before Sunrise
Romance starring Julie Delpy and Ethan Hawke. Two twentysomethings meet on a train and decide to spend a few hours together. Contains some strong language.  Also in HD. [1995] [AD,S]
1392418980

550744512
2637755808
f:0,c:0013ec,c:0113ed,c:0213ef,c:0313ec
188
0

test3.ts.meta

1:0:1:2404:7F9:2:11A0000:0:0:0:
Love & Other Drugs
(2010) Fact-based adult comedy. Jake Gyllenhaal stars as a successful Viagra salesman who falls for a woman with Parkinson's (Anne Hathaway). Strong language/sexual scenes.  [AD,S]
1472775840

712401799
2824257448
f:0,c:000931,c:010932,c:020934,c:030931
188
0

test4.ts.yuan

1:0:1:2404:7F9:2:11A0000:0:0:0:
Departures
(2008) An Oscar-winning, whimsical look at the Japanese undertaking profession. Masahiro Motoki stars as a musician starting a new career preparing the dead for burial. Japanese/subs.
1400111580

863881200
3699150040
f:0,c:000931,c:010932,c:020934,c:030931
188
0

.csvファイルを多くの.ts.metaファイルと同じディレクトリに配置します。ディレクトリ内の各.ts.metaファイルに対して、.csvファイルには対応する映画名を含む行があります。

.csvファイルの各行を繰り返し、名前付き.ts.metaファイルの2行目を.csvファイルで指定された対応する映画の名前に置き換えるsed、awk、またはgawkを使用するスクリプトをどのように作成できますか?

以下のソリューションで提供された例を試しましたが、何が起こっているのかわかりません!

ありがとう、

柔軟

答え1

単にテキストを操作するためにシェルループを作成しないでください。シェルループを使用してテキストを処理することが悪い習慣と見なされる理由、リテラル文字列を使用するには、リテラル文字列を理解していないsedなどのツールではなく、リテラル文字列を理解するawkなどのツールを使用します。

.ts.metaテストするファイルを提供していないため、明らかにテストされていませんが、同様の-i inplace操作がGNU awkを使用して行われます(元のファイルを変更したい場合)ARGIND

awk -i inplace -F',' '
    NR == FNR {
        titles[ARGC] = $2
        ARGV[ARGC++] = $1
    }
    (NR != FNR) && (FNR == 2) {
        $0 = titles[ARGIND]
    }
    { print }
' 1TBMovie2_dotTSdotMeta.txt

本当にsedでこれをやりたい場合(しないでください)、以下を参照してください。sedを使用して正規表現のメタ文字を確実にエスケープすることは可能ですか?そして、これが&心配すべき唯一のキャラクターではないことに注意してください。たとえば、処理する必要があるキャラクター/もあります。\1

新しく提供された入力例を考えると、次のようになります。

$ head -n 50 update* *.meta
==> updatemeta.txt <==
test1.ts.meta,Carols from King's (2013)
test2.ts.meta,Before Sunrise (1995)
test3.ts.meta,Love & Other Drugs (2010)
test4.ts.meta,Departures (2008)

==> test1.ts.meta <==
1:0:19:1B1C:802:2:11A0000:0:0:0:
Carols from King's
The traditional Christmas carol concert from King's College Chapel, Cambridge. Stephen Cleobury conducts the famous chapel choir in carols old and new. [HD] [S]
1387969020

448066800
2913369072
f:0,c:00157c,c:01157e,c:02157f,c:03157c,c:050001
188
0

==> test2.ts.meta <==
1:0:1:189E:7FD:2:11A0000:0:0:0:
Before Sunrise
Romance starring Julie Delpy and Ethan Hawke. Two twentysomethings meet on a train and decide to spend a few hours together. Contains some strong language.  Also in HD. [1995] [AD,S]
1392418980

550744512
2637755808
f:0,c:0013ec,c:0113ed,c:0213ef,c:0313ec
188
0

==> test3.ts.meta <==
1:0:1:2404:7F9:2:11A0000:0:0:0:
Love & Other Drugs
(2010) Fact-based adult comedy. Jake Gyllenhaal stars as a successful Viagra salesman who falls for a woman with Parkinson's (Anne Hathaway). Strong language/sexual scenes.  [AD,S]
1472775840

712401799
2824257448
f:0,c:000931,c:010932,c:020934,c:030931
188
0

==> test4.ts.meta <==
1:0:1:2404:7F9:2:11A0000:0:0:0:
Departures
(2008) An Oscar-winning, whimsical look at the Japanese undertaking profession. Masahiro Motoki stars as a musician starting a new career preparing the dead for burial. Japanese/subs.
1400111580

863881200
3699150040
f:0,c:000931,c:010932,c:020934,c:030931
188
0

以下は実行されるawkスクリプトです。

$ awk -i inplace -F',' '
    NR == FNR {
        titles[ARGC] = $2
        ARGV[ARGC++] = $1
    }
    (NR != FNR) && (FNR == 2) {
        $0 = titles[ARGIND]
    }
    { print }
' updatemeta.txt

ファイルで実行される操作は次のとおりです。

$ head -n 50 update* *.meta
==> updatemeta.txt <==
test1.ts.meta,Carols from King's (2013)
test2.ts.meta,Before Sunrise (1995)
test3.ts.meta,Love & Other Drugs (2010)
test4.ts.meta,Departures (2008)

==> test1.ts.meta <==
1:0:19:1B1C:802:2:11A0000:0:0:0:
Carols from King's (2013)
The traditional Christmas carol concert from King's College Chapel, Cambridge. Stephen Cleobury conducts the famous chapel choir in carols old and new. [HD] [S]
1387969020

448066800
2913369072
f:0,c:00157c,c:01157e,c:02157f,c:03157c,c:050001
188
0

==> test2.ts.meta <==
1:0:1:189E:7FD:2:11A0000:0:0:0:
Before Sunrise (1995)
Romance starring Julie Delpy and Ethan Hawke. Two twentysomethings meet on a train and decide to spend a few hours together. Contains some strong language.  Also in HD. [1995] [AD,S]
1392418980

550744512
2637755808
f:0,c:0013ec,c:0113ed,c:0213ef,c:0313ec
188
0

==> test3.ts.meta <==
1:0:1:2404:7F9:2:11A0000:0:0:0:
Love & Other Drugs (2010)
(2010) Fact-based adult comedy. Jake Gyllenhaal stars as a successful Viagra salesman who falls for a woman with Parkinson's (Anne Hathaway). Strong language/sexual scenes.  [AD,S]
1472775840

712401799
2824257448
f:0,c:000931,c:010932,c:020934,c:030931
188
0

==> test4.ts.meta <==
1:0:1:2404:7F9:2:11A0000:0:0:0:
Departures (2008)
(2008) An Oscar-winning, whimsical look at the Japanese undertaking profession. Masahiro Motoki stars as a musician starting a new career preparing the dead for burial. Japanese/subs.
1400111580

863881200
3699150040
f:0,c:000931,c:010932,c:020934,c:030931
188
0

答え2

1つの方法は、正規表現パスをバイパスし、readrコマンドを使用することですsed

cat 1TBMovie2_dotTSdotMeta.txt | while IFS=, read file moviename; do printf '%s\n' "$moviename" | sed -i -e '2r /dev/stdin' -e '2d' "$file"; done

次のように読みやすいように複数行で記述する必要があります。

cat 1TBMovie2_dotTSdotMeta.txt | 
while IFS=, read file moviename
do
   printf '%s\n' "$moviename" |
   sed -i -e '2r /dev/stdin' -e '2d' "$file"
done

ここでは、gnu sed関数を使用してファイルを読み込みますstdin。 GNUでない場合は、sedムービー名を一時ファイルに保存し、その名前をコマンドに使用できますr。今何でも逃げようと努力する必要はありません。

ただし、追加ファイルの手間がかからない場合は、コマンド/ \ &のrhsから特殊文字をエスケープする必要がありますsed s/.../...//区切り文字として機能するため含まれます。

cat 1TBMovie2_dotTSdotMeta.txt |
while IFS=, read file moviename
do
    moviename_esc=$(printf '%s\n' "$moviename" | sed -e 's:[\&/]:\\&:g')
    sed -i -e "2 s/.*/$moviename_esc/" "$file"
done

関連情報