最初の一致パターンの前にのみ行ブロックを挿入する

最初の一致パターンの前にのみ行ブロックを挿入する

server {/etc/nginx/nginx.conf で最初に一致する文字列の前に次の行を挿入する必要があります (変数置換後)。

変える:

website=www.hello.com

ラインブロック:

server {
# Permanent redirect to www
server_name  ${website:4};
rewrite ^/(.*)$ http://$website/$1 permanent;
}

変数置換後に挿入する行ブロックは、次のようにする必要があります。

server {
# Permanent redirect to www
server_name  hello.com;
rewrite ^/(.*)$ http://www.hello.com/$1 permanent;
}

私が試した次の試みには2つの問題があります。

問題1:コードは、最初のパターンだけでなく、各(複数の)一致パターンの前に行ブロックを追加します。

問題2:変数の値websiteが置き換えられません。www.hello.com

cat myattempt.sh
awk '
/server {/ {
    print "server {"
    print "# Permanent redirect to www"
    print "server_name  ${website:4};"
    print "rewrite ^/(.*)$ http://$website/$1 permanent;"
    print "}"
}
{ print }
' /etc/nginx/nginx.conf > /etc/nginx/nginx.conf.tmp
mv /etc/nginx/nginx.conf.tmp /etc/nginx/nginx.conf

私の試みをテストするには/etc/nginx/nginx.conf

Cat/etc/nginx/nginx.conf

http 
{
#  server   {
}

server  { 
}
}

myattempt.shの実行

現在の出力:cat /etc/nginx/nginx.conf

http 
{

server {
# Permanent redirect to www
server_name  ${website:4};
rewrite ^/(.*)$ http://$website/$1 permanent;
}

#  server   {
}

server {
# Permanent redirect to www
server_name  ${website:4};
rewrite ^/(.*)$ http://$website/$1 permanent;
}
server  { 
}
}

予想出力:

Cat/etc/nginx/nginx.conf

http 
{

server {
# Permanent redirect to www
server_name  hello.com;
rewrite ^/(.*)$ http://www.hello.com/$1 permanent;
}

#  server   {
}

server  { 
}
}

何か提案してもらえますか?

答え1

これはおそらくあなたが望むものです:

$ cat tst.sh
#!/usr/bin/env bash

website=www.hello.com

new='
server {
# Permanent redirect to www
server_name  '"${website:4}"';
rewrite ^/(.*)$ http://'"$website"'/$1 permanent;
}
'

awk -v new="$new" '
    /server *\{/ && !f++ {
        print new
    }
    { print }
' "${@:-}"

$ ./tst.sh file
http
{

server {
# Permanent redirect to www
server_name  hello.com;
rewrite ^/(.*)$ http://www.hello.com/$1 permanent;
}

#  server   {
}

server  {
}
}

同じ名前のシェル変数でawk変数を入力すると-vエスケープシーケンスが解釈されるため、同じ文字列はリテラルタブと改行文字になります。これが問題の場合、またはを使用してシェル変数の値を取得します。new\t\nENVIRON[]ARGV[]awkスクリプトでシェル変数を使用する方法

答え2

リンクしてもいいかわかりません。sed 回答奇妙な質問をすることは失礼と見なされますが、まだ:D

また、www.このセクションは次のため印刷されません。BASHパラメータ拡張。インデックス 4 で印刷を開始するよう指定すると、最初の 4 文字が削除されます。

例:

$ foo='0123456789'; echo ${foo:3:5}

出力34567

編集:まあ、ここにスタンドアロン評価、envsubst、awkソリューションがあります。

複数行の検索と置換がPITAであることがわかりました。複数行を置き換える単一行検索の場合、最良の方法は1つの言語を使用することです。私はawkの例を見つけました変数の検索と置換そして最初の交換が発生しましたperl -pe解決が出るずっと前に 。

# Outputs a space delimetered, dollar-sign prepended text of variables
# e.g. args: 'foo' 'bar'
# output: '$foo $bar'
generate_multi_variable_string() {
    for item in $@; do
        # Prepend dollar-sign to the beginning of all variables, with an escape beforehand
        printf '$'
        printf "$item"
        printf ' '
    done
}

substitute_into_template() {
    template="$1"

    # Rest of the arguments as dollar-sign prepended and space delimetered
    variables="$(generate_multi_variable_string ${@:2})"

    # Export variables for envsubst command to properly function
    for item in ${@:2}; do
        eval "export local $item=\"\$$item\""
    done

    # Here-doc of template, into content of which provided variables are substituted
    envsubst "$variables" << EOF
$template
EOF
}

template='server {
# Permanent redirect to www
server_name  $website;
rewrite ^/(.*)$ http://$website/$1 permanent;'

website='www.hello.com'

match="server {"
replace="$(substitute_into_template "$template" website)"

cat nginx.conf | awk -v srch="$match" -v repl="$replace" '!x{x=sub(srch,repl,$0)} { print $0 }' > new-nginx.conf

関連情報