sed を使用してあるファイルから別のファイルに文字列を置換するときに、「置換コマンドのフラグが正しくありません: '{"」

sed を使用してあるファイルから別のファイルに文字列を置換するときに、「置換コマンドのフラグが正しくありません: '{"」

File1にある文字列をFile2の文字列に置き換えようとしています

ファイル1

<IMG SRC="/Repository/GetImage.dll?baseHref=Orange/2011/03/27&amp;EntityID=Ad12911&amp;imgExtension=" />
<IMG SRC="/Repository/GetImage.dll?baseHref=Orange/2011/03/20&amp;EntityID=Ad13304&amp;imgExtension=" />
<IMG SRC="/Repository/GetImage.dll?baseHref=Orange/2010/08/29&amp;EntityID=Ad13724&amp;imgExtension=" />

ファイル2

/getimage.dll?path=Orange/2011/03/27/129/Img/Ad1291103.gif
/getimage.dll?path=Orange/2011/03/20/133/Img/Ad1330402.gif
/getimage.dll?path=Orange/2010/08/29/137/Img/Ad1372408.gif

このコマンドを実行すると

$ sed -e 's/.*SRC="\/Repository\([^"]*\)".*/\1/p{r File1' -e 'd}' File2

このエラーが発生します

sed: 1: "s/.*SRC="\/Repository\( ...": bad flag in substitute command: '{'

正規表現に何か問題がありますか?

私が達成しようとしている結果は、File1 が次のようになることです。

ファイル1

<IMG SRC="/Repository/getimage.dll?path=Orange/2011/03/27/129/Img/Ad1291103.gif" />
<IMG SRC="/Repository/getimage.dll?path=Orange/2011/03/20/133/Img/Ad1330402.gif" />
<IMG SRC="/Repository/getimage.dll?path=Orange/2010/08/29/137/Img/Ad1372408.gif" />

答え1

File1二重引用符内のすべてを新しいイメージ名に置き換えようとしている場合は、File2awk を使用します。

awk -F'"' 'NR==FNR{a[i++]=$1;next}{print $1 FS a[j++] FS $3}' File2 File1

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

<IMG SRC="/getimage.dll?path=Orange/2011/03/27/129/Img/Ad1291103.gif" />
<IMG SRC="/getimage.dll?path=Orange/2011/03/20/133/Img/Ad1330402.gif" />
<IMG SRC="/getimage.dll?path=Orange/2010/08/29/137/Img/Ad1372408.gif" />

答え2

あなたがそこで何をしようとしているのか全く分かりませんが、私の sed スキルはそれほど強くないので、私が知らない難解な構文を使用しているのだと思います。あなたの sed の何が問題なのかは分かりませんが (ただし、推測ですが、置換文字列に含まれる特殊文字 ( など) が問題を引き起こしていると思われます/) ?、代わりに Perl の代替案を提案します。

perl -i -pe 'BEGIN{open($f,shift); while(<$f>){chomp; push @F,$_}}
            $k=shift(@F); s/(.*SRC=.)([^"]*)/$1$k/' file2 file1 

わかりやすくするために、同じ内容をコメント付きスクリプトとして記述したものがこちらです。上記のワンライナーでは、 によって、-iと同様に実際の入力ファイルが変更されますsed -i

#!/usr/bin/env perl

## This is the equivalent of the BEGIN{} block.
## @ARGV is the array of arguments and shift returns
## the first element of it. This is file2 which is
## then opened, each line is read, its trailing \n
## is removed by chomp and it is then added to the @F array.
my $file=shift(@ARGV);
open($f,$file);
while(<$f>){chomp; push @F,$_}

## This is the rest of the oneliner above. The -pe options
## cause the file to be read and each line printed after 
## the script is applied. Since the previous block removed 
## file2 from @ARGV, this is applied to file1 only.
while (<>) {
    ## Remove the 1st item of @F. This is a line of file2.
    $k=shift(@F);

    ## Make the substitution. The \ before the " is not 
    ## needed, I just added it here because otherwise, the 
    ## syntax highlighting is broken. 
    s/(.*SRC=.)([^\"]*)/$1$k/;
    ## This print is implied by the -p flag
    print;
}

答え3

sこのエラーは、正規表現ではなく、sed コマンドが間違っていることを示しています。コマンドと次のコマンドを区切るには、改行またはセミコロンが必要です{。同様に、それらを別々の引数に置くこともできます-e

sed -e 's/ です。SRC="/リポジトリ([^"])".*/\1/p' -e '{' -e 'r ファイル1' -e 'd' -e '}' ファイル2

ただし、これは必要な動作ではありません。…SRC="Repository/入力からプレフィックスと次の二重引用符で始まる部分を削除し、置換された行のみを出力します (コマンドpのフラグsとそれに続く のためd)。そして、入力行ごとに (一致しているかどうかに関係なく) のコピーを挿入しますFile1

2 つのファイルのデータを一致させたい場合は、sed¹ よりも強力なツールが必要になります。ぎこちないまたはパール良い選択です。

¹技術的には、sed はチューリング完全ですが、sed でそれを実行すると非常に複雑でわかりにくくなります。

関連情報