sed - 必要に応じて引用符を使用するように値を置き換えます。

sed - 必要に応じて引用符を使用するように値を置き換えます。

100を超えるjinjaテンプレートファイルがあり、"value:..."文字列が各ファイルに0-k回表示されます。問題は、いくつかのファイルが以下を使用していることです。

value: something

そのうちのいくつかは次のとおりです。

value: 'something'

それらのいくつか:

value: "some other thing"

二重引用符を使用して、すべて同じように見えるようにする必要があります。私はこれを行うためにsedを使うと思います。

sed -i 's/value: ['"]?(.*)['"]?/value: "\1"/g' *.j2

しかし、私が見たように、私はsedが嫌いだったので、過去2時間で終了しなかった "s"コマンドなどの無意味なエラーメッセージでキーボードを破壊したかったのです。

入力例:

- param:
  name: Command
  type: String
  value: '/bin/echo'
- param:
  name: Args
  type: String
  value: Hello World
- param:
  name: Something
  type: EnvVar
  value: "PATH"

これから私は以下を得るべきです:

- param:
  name: Command
  type: String
  value: "/bin/echo"
- param:
  name: Args
  type: String
  value: "Hello World"
- param:
  name: Something
  type: EnvVar
  value: "PATH"

答え1

"'式に両方の形式の引用符()を使用する必要がある場合、状況は難しくなります。まず、最初の試みでは、シェルはそれを引用符's/value: ['付き文字列として識別します。後者の引用は保存されません。

このような場合は心配する必要はありません。 Sedコマンドをファイルに入れます。その内容はシェル操作の対象になりません。

quotes.sed:

# (1) If line matches this regex (value: '), 
# (2) substitute the first ' with " and
# (3) substitute the ' in the end-of-line with ".
/value: '/{
  s/'/"/
  s/'$/"/
}
# (4) If line matches this regex (value: [^"]), 
# (5) substitute :<space> for :<space>" and
# (6) append a " in the end-of-line.
/value: [^"]/{
  s/: /: "/
  s/$/"/
}
$ sed -Ef quotes.sed file
- param:
  name: Command
  type: String
  value: "/bin/echo"
- param:
  name: Args
  type: String
  value: "Hello World"
- param:
  name: Something
  type: EnvVar
  value: "PATH"

答え2

通話sedには2つの問題があります。

  • 一重引用符で囲まれたプログラムには、['"]正規表現の一部としてリテラル一重引用符が含まれます。sed一重引用符内の一重引用符はエスケープできないため機能しません。しかし、で表現できます\x27
  • この... (.*) ...構文は拡張正規表現構文で(あり、)デフォルトでは「グループキャプチャ」を意味します。-Eオプションを使用するsedか、キャプチャグループを\(.*\)使用して定義する必要があります。基本正規表現?(しかし、同様のものと交換する必要があります\{0,1\}。)

私のテストでは、次のことが動作します。

sed -E 's/value: [\x27"]?([^\x27"]*)[\x27"]?/value: "\1"/' input.j2

答え3

GNU awkを使用してmatch()とgensub()に3番目の引数を渡します。

$ awk 'match($0,/(\s*value:\s*)(.*)/,a){$0=a[1] "\"" gensub(/[\047"]/,"","g",a[2]) "\""} 1' file
- param:
  name: Command
  type: String
  value: "/bin/echo"
- param:
  name: Args
  type: String
  value: "Hello World"
- param:
  name: Something
  type: EnvVar
  value: "PATH"

それ以外の場合は awk を使用してください。

$ awk '/value:/{hd=$0; sub(/:.*/,": ",hd); gsub(/[^:]*: *[\047"]?|[\047"]$/,"");  $0=hd "\"" $0 "\""} 1' file
- param:
  name: Command
  type: String
  value: "/bin/echo"
- param:
  name: Args
  type: String
  value: "Hello World"
- param:
  name: Something
  type: EnvVar
  value: "PATH"

答え4

Raku(旧Perl6)を使う

Larry Wallという紳士が「perl6-users」メーリングリストにこのきれいな引用のヒントを投稿しました。[Eメール保護])。以下のNNTPリンクのヒント#8を参照してください。

~$ env re="\'" raku -ne 'say $0 if m/ <?after value\:\s >  \"? <{ %*ENV<re> }>?  (.+?) \"? <{ %*ENV<re> }>? $$ /;'  jinja.txt
「/bin/echo」
「Hello World」
「PATH」

上記のコードは正しい一致を示しています。したがって、必要なのは次のコードを実行するだけです。

~$ env re="\'" raku -pe 's/ <?after value\:\s >  \"? <{ %*ENV<re> }>?  (.+?) \"? <{ %*ENV<re> }>? $$ /"{$0}"/;'  jinja.txt
- param:
  name: Command
  type: String
  value: "/bin/echo"
- param:
  name: Args
  type: String
  value: "Hello World"
- param:
  name: Something
  type: EnvVar
  value: "PATH"

脱出をもっと読みやすくしたいですか?上記のようなENV変数を使用したくありませんか?次に、引用符の綴りを入力します(下のNNTPリンクのLarry Wallのヒント#8でも参照)。

~$ raku -ne 'say $0 if m/ <?after value\:\s >  \c[QUOTATION MARK]? \c[APOSTROPHE]?  (.+?)  \c[APOSTROPHE]? \c[QUOTATION MARK]? $$ /;'  jinja.txt
「/bin/echo」
「Hello World」
「PATH」

~$ raku -pe 's/ <?after value\:\s >  \c[QUOTATION MARK]? \c[APOSTROPHE]?  (.+?)  \c[APOSTROPHE]? \c[QUOTATION MARK]? $$ /"{$0}"/;'  jinja.txt
- param:
  name: Command
  type: String
  value: "/bin/echo"
- param:
  name: Args
  type: String
  value: "Hello World"
- param:
  name: Something
  type: EnvVar
  value: "PATH"

HTH。

https://raku.org/
https://www.nntp.perl.org/group/perl.perl6.users/2020/07/msg9004.html

関連情報