sedを使用して同じ一致行を削除します。

sedを使用して同じ一致行を削除します。

このbashスクリプトがあります。

sed -i -r '/deb http\:\/\/httpredir\.debian\.org\/debian jessie main/d' /etc/apt/sources.list
sed -i -r '/deb http\:\/\/httpredir\.debian\.org\/debian jessie\-updates main/d' /etc/apt/sources.list
sed -i -r '/deb http\:\/\/security\.debian\.org jessie\/updates main/d' /etc/apt/sources.list
echo -e 'deb http://httpredir.debian.org/debian stable main contrib non-free\ndeb-src http://httpredir.debian.org/debian stable main contrib non-free\ndeb http://httpredir.debian.org/debian jessie-backports main contrib non-free\ndeb-src http://httpredir.debian.org/debian jessie-backports main contrib non-free\ndeb http://httpredir.debian.org/debian jessie-updates main contrib non-free\ndeb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free\ndeb http://security.debian.org jessie/updates main contrib non-free\ndeb-src http://security.debian.org jessie/updates main contrib non-free' >> /etc/apt/sources.list

このシーケンスを実行しても問題はなく、一致する行が Debian ソースリストファイルから削除されます。しかし、最初にエコーすると、行を削除するのではなく、行5-7も削除されます。

SPACEを\ sに変更しても役に立ちません。

これは後でDockerfileが十分に速く更新されず、Debianが新しいマイナーバージョンをリリースしたときに問題を引き起こす可能性があります。

この正規表現にグローバルラベルが適用されているようです。行の始まりと終わりを定義することはbashにも役立ちません(regexrではうまく機能しますが、それが私が得たいものです)。 http://regexr.com/3b910

sedを使用して/igmフラグを定義できないようです。 sed は依然として完全一致行を削除します。

編集:この方法で短縮しましたが、ファイルのすべての内容が削除されたため、間違っています。

sed /etc/apt/sources.list -i -e '\!deb http://httpredir\.debian\.org/debian jessie main$!d' -e '\!deb http://httpredir\.debian\.org/debian jessie-updates main$!d' -e '\!deb http://security\.debian\.org jessie/updates main$!d' -e '$a \ndeb http://httpredir.debian.org/debian stable main contrib non-free\ndeb-src http://httpredir.debian.org/debian stable main contrib non-free\ndeb http://httpredir.debian.org/debian jessie-backports main contrib non-free\ndeb-src http://httpredir.debian.org/debian jessie-backports main contrib non-free\ndeb http://httpredir.debian.org/debian jessie-updates main contrib non-free\ndeb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free\ndeb http://security.debian.org jessie/updates main contrib non-free\ndeb-src http://security.debian.org jessie/updates main contrib non-free'

以下は問題に対する修正です(RUNコマンドはDockerfileスクリプトです)。

RUN sed -i '/^deb http\:\/\/httpredir\.debian\.org\/debian jessie main$\|^deb http\:\/\/httpredir\.debian\.org\/debian jessie\-updates main$\|^deb http\:\/\/security\.debian\.org jessie\/updates main$/d' /etc/apt/sources.list
RUN echo -e 'deb http://httpredir.debian.org/debian stable main contrib non-free\ndeb-src http://httpredir.debian.org/debian stable main contrib non-free\ndeb http://httpredir.debian.org/debian jessie-backports main contrib non-free\ndeb-src http://httpredir.debian.org/debian jessie-backports main contrib non-free\ndeb http://httpredir.debian.org/debian jessie-updates main contrib non-free\ndeb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free\ndeb http://security.debian.org jessie/updates main contrib non-free\ndeb-src http://security.debian.org jessie/updates main contrib non-free' >> /etc/apt/sources.list

アンインストールプロセスとエコープロセスを分離した理由は、デフォルトでsedがインストールされていないが、エコーがある可能性がある別の新しい超軽量LinuxディストリビューションでこのDockerfileを使用するためです。これにより、行を削除できなくても変更内容が反映されます。

複数行ソリューションの問題は、軽量(1つのDockerfileのみ)に保ち、外部.shスクリプトを含めたくないことです。

ベストアンサー1

sed パターンは最後に固定されていないため、新しい行と一致します。別の解決策は、行を削除して読み込むのではなく、行を変更することです。

まず、広すぎないようにして、元のスクリプトをより読みやすくすることができるかどうかを見てみましょう。

sed -i -r '/deb http\:\/\/httpredir\.debian\.org\/debian jessie main/d' /etc/apt/sources.list
sed -i -r '/deb http\:\/\/httpredir\.debian\.org\/debian jessie\-updates main/d' /etc/apt/sources.list
sed -i -r '/deb http\:\/\/security\.debian\.org jessie\/updates main/d' /etc/apt/sources.list
cat >> /etc/apt/sources.list << EOF
deb http://httpredir.debian.org/debian stable main contrib non-free
deb-src http://httpredir.debian.org/debian stable main contrib non-free
deb http://httpredir.debian.org/debian jessie-backports main contrib non-free
deb-src http://httpredir.debian.org/debian jessie-backports main contrib non-free
deb http://httpredir.debian.org/debian jessie-updates main contrib non-free
deb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free
deb http://security.debian.org jessie/updates main contrib non-free
deb-src http://security.debian.org jessie/updates main contrib non-free
EOF

実際、1つのsedコマンドですべての操作を実行できない理由はありません。

sed /etc/apt/sources.list -i \
  -e '\!deb http://httpredir\.debian\.org/debian jessie main$!d' \
  -e '\!deb http://httpredir\.debian\.org/debian jessie-updates main$!d' \
  -e '\!deb http://security\.debian\.org jessie/updates main$!d' \
  -e '$a \
deb http://httpredir.debian.org/debian stable main contrib non-free\
deb-src http://httpredir.debian.org/debian stable main contrib non-free\
deb http://httpredir.debian.org/debian jessie-backports main contrib non-free\
deb-src http://httpredir.debian.org/debian jessie-backports main contrib non-free\
deb http://httpredir.debian.org/debian jessie-updates main contrib non-free\
deb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free\
deb http://security.debian.org jessie/updates main contrib non-free\
deb-src http://security.debian.org jessie/updates main contrib non-free'

それでは私がしたことについて話しましょう。まず、パターンの末尾に$を追加することです。ただし、単一のsedコマンドを使用すると、競合状態ウィンドウがはるかに狭くなり、sedが完了するまで元のファイルがそのまま残るため、この時点ではこれは必要ありません。 sed は一時ファイルを元のファイルの上にコピーします。これは一度だけ発生します。以下は、余分なエスケープを減らすことです。特に - と : は基本または拡張正規表現の特殊文字ではないため、エスケープする必要はありません(そうすることで、POSIX によって正式に定義されていない動作が発生する可能性がありますが、実際にはほとんど行われません)。これによりエスケープすべきスラッシュが多いので、区切り記号を!なぜなら \c マッチング演算子を使うとどこにも使われないからです。基本正規表現と拡張正規表現の違いについて言えば、議論の余地がある演算子を使用しないので、パターンがどのように解釈されるかは重要ではないので -r オプションを削除してみましょう。 1つのsed呼び出しで複数のsedコマンドを使用するので、-eオプションが必要で、各sedコマンドに必要です。この場合、コマンドが変更されるファイルの前に来る必要がないという追加の利点があります。 aコマンドで新しい行を追加して終了し、$に制限して最後の行でのみ実行します。エスケープしないと、6文字を保存できます。パターンやurlが長い特性上、自分自身も一致し、他とも一致する可能性が低いため、この程度で十分です。

または、Perlのバージョンは次のようになります。

perl -pi \
  -e 'next if m!deb http://httpredir\.debian\.org/debian jessie main$!;' \
  -e 'next if m!deb http://httpredir\.debian\.org/debian jessie-updates main$!;' \
  -e 'next if m!deb http://security\.debian\.org jessie/updates main$!;' \
  -e 'END print "
deb http://httpredir.debian.org/debian stable main contrib non-free
deb-src http://httpredir.debian.org/debian stable main contrib non-free
deb http://httpredir.debian.org/debian jessie-backports main contrib non-free
deb-src http://httpredir.debian.org/debian jessie-backports main contrib non-free
deb http://httpredir.debian.org/debian jessie-updates main contrib non-free
deb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free
deb http://security.debian.org jessie/updates main contrib non-free
deb-src http://security.debian.org jessie/updates main contrib non-free\n";}'

次のようになります。

perl -pie 'next if m!deb http://httpredir\.debian\.org/debian jessie main$!; next if m!deb http://httpredir\.debian\.org/debian jessie-updates main$!; next if m!deb http://security\.debian\.org jessie/updates main$!; END{ print "deb http://httpredir.debian.org/debian stable main contrib non-free\ndeb-src http://httpredir.debian.org/debian stable main contrib non-free\ndeb http://httpredir.debian.org/debian jessie-backports main contrib non-free\ndeb-src http://httpredir.debian.org/debian jessie-backports main contrib non-free\ndeb http://httpredir.debian.org/debian jessie-updates main contrib non-free\ndeb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free\ndeb http://security.debian.org jessie/updates main contrib non-free\ndeb-src http://security.debian.org jessie/updates main contrib non-free\n";}'

おすすめ記事