ファイルの内容で一致する正規表現を変数に置き換えます。

ファイルの内容で一致する正規表現を変数に置き換えます。

次のことをしたい

  1. パターン()を使用して^[ \t]*services:[ \t]*ファイルの内容を検索する
  2. 見つかったら、パターンを文字列に置き換えます(変数内)。
  3. それ以外の場合は、文字列(変数)をファイルの末尾に追加します。

ステップ2で停止しました。スクリプトのステップ2はservices:ファイル内で置き換えられます${serviceLoopBack}。私のコマンドには何の問題がありますかsed

テストスクリプト

#!/bin/bash
set -e

destfile=config.yml

serviceLoopBack="services:|NL|- name: loopback-service|NL||FS||FS|url: http://127.0.0.1:12345|NL||FS||FS|routes:|NL||FS||FS|- name: loopback-test-route"
serviceLoopBackWithFrontSpace="|NL||NL|$serviceLoopBack"

if grep -E "^[ \t]*services:[ \t]*" $destfile
then
    # service tag found, replace target string
    sed -i -e 's/^[ \t]*services:[ \t]*/${serviceLoopBack}/g' $destfile
else
    # service tag not found, append at end of file
    echo $serviceLoopBackWithFrontSpace >> $destfile
fi

# replace separator 1 to new line
sed  -i -e 's/|NL|/\n/g' $destfile

# replace separator 2 to space
sed  -i -e 's/|FS|/ /g' $destfile

ベストアンサー1

問題は、2番目のsed呼び出しでプログラムを一重引用符()で囲むことです' ... '。これは推奨される方法ですが、一重引用符を使用すると、シェルがシェル変数(たとえば)を拡張するのを防ぐことができるため、テキスト${serviceLoopBack}はシェル変数の内容に置き換えられずに残ります。

1つの可能性は、次のように単一引用符の代わりに二重引用符を使用することです。

sed -i -e "s,^[ \t]*services:[ \t]*,${serviceLoopBack}," "$destfile"

または、sed次のコマンドを使用して式をシェル変数にアセンブルしますprintf

printf -v prog 's,^[ \t]*services:[ \t]*,%s,' "$serviceLoopBack"
sed -i -e "$prog" "$destfile"

ノート代替テキストも含まれているため、,区切り文字として使用しています。それ以外の場合は混乱する可能性があります。また、行ごとに一致が1つしかないと仮定しているため、そのオプションは省略しました。//sedg

とにかくシェルスクリプトの参照を見たいかもしれません。たとえば、この回答理由について。

ただし、sed厳密に要求されない場合は、ほぼ完全なシェルスクリプトをプログラムに置き換えることができますawk(より高速)。

awk -v slb="services:|NL|- name: loopback-service|NL||FS||FS|url: http://127.0.0.1:12345|NL||FS||FS|routes:|NL||FS||FS|- name: loopback-test-route" \
 '/^[ \t]*services:/{$0=slb;f=1}
  {gsub(/\|NL\|/,"\n"); gsub(/\|FS\|/," ")} 1; END{if (!f) {print "\n\n" slb}}' "$destfile"
  • awkこれにより、変数に「サービスループバック」仕様がインポートされますslb
  • 次に、パターンに一致する行があるかどうかを確認しservices:、その場合は行全体を保存された文字列に置き換えますslb(私の考えでは、これが実際に達成したい文字列です)。同時にフラグをf1に設定します。
  • すべての改行文字とすべての空白の発生gsub()を置き換えるには、を使用します。|NL||FS|
  • 一見すると、「汚れた」コマンドは、これまでに変更されたすべての内容を含む現在の行を印刷するように指示1します。awk
  • 最後にfまだ設定されていない場合は、先行パターンを「サービスループバック」行に追加します(ただし、に変換されます\n\n)。

awkこのオプションを理解する実装がないと、ファイルは内部で編集されません。出力を一時ファイルにリダイレクトし、それを一時ファイルに置き換える必要があります。awk-i inplace$destfile

ただし、要約すると、構造化言語(YAML)で作業しているので、専用パーサーを使用することをお勧めしyqます(行ベースのテキスト処理ツールの代わりに)。

おすすめ記事