첫 번째 일치 패턴 앞에만 행 블록 삽입

첫 번째 일치 패턴 앞에만 행 블록 삽입

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;
}

내가 시도한 다음 시도에는 두 가지 문제가 있습니다.

문제 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다음을 만듭니다.

고양이/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  { 
}
}

예상 출력:

고양이/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임이 밝혀졌습니다. 여러 줄을 바꾸는 단일 줄 검색의 경우 가장 좋은 방법은 하나의 언어를 사용하는 것입니다. 나는 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

관련 정보