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