2つのインスタンスのいずれかを置き換えるためにsed one-linerを作成しようとしたとき
infra/helm/*/charts/*
または
infra/helm/*/charts/
"infra/helm/*/charts/*" を含むファイル内の改行文字と次のような他のテキスト行
infra/helm/*/charts/*
infra/helm/*/manifests/
このパターンを正常に検出し、このコード行を使用して通常のzsh(バージョン:zsh 5.7.1(x86_64-apple-darwin19.0))ターミナルウィンドウでパターンを置き換えました。
sed -E $'s/infra\\/helm\\/\\*\\/charts\\/(\\*)\*/infra\\/helm\\/\\*\\/charts\\/\\*\\\ninfra\\/helm\\/\\*\\/manifests\\//' myfile
(GNU) sed に '-i' フラグが導入されたときの動作に奇妙な変化が生じました。このフラグを使用して同じ行を実行するとき
(つまり
sed -iE $'s/infra\\/helm\\/\\*\\/charts\\/(\\*)\*/infra\\/helm\\/\\*\\/charts\\/\\*\\\ninfra\\/helm\\/\\*\\/manifests\\//' datfile
)
ファイルが変更されていないことがわかりました。一般的に、私はこれがファイル権限のいくつかの特異性や直接のターミナルエントリではなくスクリプトを呼び出すことによって生成されるプロセスが原因であると仮定していますが、奇妙なことに確認しました。
sed -iE $'s/infra\\/helm\\/\\*\\/charts\\/\\*/infra\\/helm\\/\\*\\/charts\\/\\*\\\ninfra\\/helm\\/\\*\\/manifests\\//' datfile
良い結果。 (目の疲れを避けるために、この行の唯一の違いは
infra/helm/*/charts/*
受け入れずにパターンマッチで
infra/helm/*/charts/
)
これがなぜそうなのか知っている人はいますか? FWIW、上記のzshバージョンをインタプリタとして使用するかどうかにかかわらず、この動作がまだ存在することを確認しました。または GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19) Copyright (C) 2007 Free Software Foundation, Inc.
代わりに。いくつかの回避策を見つけることはそれほど難しくありませんが、私はsedのスキルを向上させたいので、これが起こる理由を理解することは私にとって非常に重要です。
実行情報ダンプを添付しました。
strings $(which sed)
次のような
$FreeBSD: src/usr.bin/sed/compile.c,v 1.28 2005/08/04 10:05:11 dds Exp $
$FreeBSD: src/usr.bin/sed/main.c,v 1.36 2005/05/10 13:40:50 glebius Exp $
$FreeBSD: src/usr.bin/sed/misc.c,v 1.10 2004/08/09 15:29:41 dds Exp $
$FreeBSD: src/usr.bin/sed/process.c,v 1.39 2005/04/09 14:31:41 stefanf Exp $
答え1
GNU sedの-i
オプションは、バックアップに使用するサフィックスであるオプションの引数を使用します。これにより、sed -iE … datfile
以前のバージョンのファイルがdatfileE
。-E
回避策は、オプションを別々に渡すことです:sed -i -E …
またはsed -E -i …
。 (-Ei
あなたのコードを読む次の人が嫌いなら大丈夫です。)
または、バックアップサフィックス(sed -E -i.bak …
)を渡すと、スクリプトをFreeBSD sedとGNU sedの両方で使用できます。このサフィックスはオプションに必須の引数があるため、BSD sedに必要であり、GNU sedをオプション引数ではなくオプションの引数として扱うには、オプション-i
と同じコマンドライン引数にする必要があります(-i
および間にスペースはありません)。 1つのパラメータを分離します。これにはバックアップファイルを生成する副作用があります。.bak
-i
sed