GNU sed - 가변 인수를 기반으로 기존 템플릿의 수정된 버전 만들기

GNU sed - 가변 인수를 기반으로 기존 템플릿의 수정된 버전 만들기

이 질문은 렌더 템플릿 사용에 관한 것입니다 sed.

템플릿 파일이 있습니다 nginx_app.

server {
    root ${drt}/${domain}/;
    server_name ${domain} www.${domain};
}

이 파일을 다른 스크립트에서 사용합니다.

#!/bin/bash
domain="$1" && test -z ${domain} && return
sed "s/\${domain}/${1}/g" "nginx_app" > "/etc/nginx/sites-available/${domain}.conf"

물론 목적은 example.com.conf이를 기반으로 렌더링 템플릿으로 사용하는 것입니다.nginx_app


위의 코드를 고려해보세요:

sed "s/\${domain}/${1}/g" "nginx_app" > "/etc/nginx/sites-available/${domain}.conf"

내가 이해한 바로는 이 코드는 다음을 수행합니다.

  1. ${domain}${1}()의 스크립트 인수를 기반으로 (아직 확장되지 않은) 문자열을 변경 합니다 example.com.메모리이지만 nginx_app파일 자체는 변경되지 않습니다.
  2. nginx_app렌더링된 버전 을 /etc/nginx/sites-available/${domain}.conf.

여기에서 정확하다고 가정하면 코드를 보면 이러한 작업이 나에게 매우 직관적이지 않다고 말해야 합니다. 이 코드에 대한 설명이 정확합니까?

내 설명이 충분히 정확하지 않은 경우 정정해 주세요.

답변1

예, 본문의 두 번째 부분에 대한 귀하의 이해가 정확합니다.

sed다른 많은 Unix 도구와 마찬가지로 다음과 같이 작동한다고 말할 수 있습니다.필터. 필터는 입력을 받아 수정하고 출력을 생성합니다. 많은 경우 필터링을 수행하는 유틸리티는 읽기 또는 쓰기 중인지조차 모를 수 있습니다.문서. 실제로 다른 필터 유틸리티에서 직접 읽거나 쓸 수 있습니다. 이는 유틸리티 자체에 투명하며 쉘에 의해 설정됩니다.

다음과 같은 불필요한 사용법 사실을 무시하십시오 cat.

cat <file | sed 's/^\([^=]*\)=\(.*\)$/#\1=\2 # old/' | tr -s ' ' >newfile

위의 유틸리티 중 어느 것도 파일 읽기 또는 쓰기에 대해 알지 못합니다. cat에서 읽다표준 입력 스트림(셸은 의 데이터를 포함하도록 배열합니다 file.) 한 번에 한 줄씩 출력을 기록합니다.표준 출력 스트림(수정이 필요하지 않습니다).

sed다음에서 읽기그것은표준 입력 스트림(셸이 연결된 출력 스트림 cat)은 각 입력 줄을 일부 수정하고 그 결과를 표준 출력 스트림(연결된 tr)에 씁니다.

tr또한 표준 출력에만 기록하지만 쉘은 출력이 파일로 이동하는 방식으로 리디렉션을 설정합니다 newfile.

프로세스의 각 단계에서 각 유틸리티는 파이프를 통해 필요한 최소한의 데이터(RAM에 할당된 버퍼)만 저장할 수 있습니다. 이는 newfile파일의 데이터를 완전히 읽기 file전에 결과가 기록되기 시작할 수 있음을 의미합니다(이 예에서는) .


구체적인 예:

sed "s/\${domain}/${1}/g" "nginx_app" > "/etc/nginx/sites-available/${domain}.conf"

무슨 일이에요:

  1. 쉘은 명령줄을 구문 분석하고 변수와 리디렉션을 찾습니다.

  2. 파일 /etc/nginx/sites-available/${domain}.conf( $domain이 변수의 값으로 확장됨)이 있으면 잘리거나 지워지고, 없으면 빈 파일로 생성됩니다.

  3. 유틸리티는 sed피연산자(해당 값으로 확장되었지만 로 이스케이프되었기 때문에 아직 확장되지 않음) 및 를 사용하여 호출됩니다. 쉘은 또한 표준 출력을 리디렉션하려는 파일에 연결합니다.s/\${domain}/${1}/g$1${domain}$\nginx_appsed

  4. 피연산자가 두 개 있으므로 sed두 번째 피연산자가 읽을 파일이라고 가정합니다. 첫 번째 피연산자에 편집 명령을 적용하면서 이를 열고 한 줄씩 읽습니다.

  5. 모든 출력은 리디렉션되는 파일로 들어갑니다.


사람들이 언급한 이후 sed -i:

-i주어진 파일을 sed변경 하게 하는 플래그sed제자리에즉, 표준 출력에 쓰지 않지만 변경 결과는 입력에 사용된 동일한 파일에 반영됩니다.

내부적으로는 sed글을 써서임시 파일나중에 원본 파일을 해당 파일로 대체합니다.

-i플래그는 하나의 인수( sedGNU 및 이 유틸리티의 일부 다른 구현의 경우 선택 사항, 다른 유틸리티의 경우 필수) 인수를 사용합니다.

sed -i .bak '...some sed script...' filename

이렇게 하면 지정된 문자열을 새 파일 이름 접미사로 사용하여 원본 파일이 백업됩니다.

나는 일반적으로 다음과 같은 이유로 사람들이 -iwith를 사용하지 못하도록 막으려고 합니다 .sed

대신에 나는 사람들에게 다음과 같은 일을 하라고 제안합니다.

sed '...some sed script...' file >file-new && mv file-new file

&& mvsed... 올바른 테스트를 거친 후에 만 부품을 추가하세요.

&& mv"이전 명령이 오류 없이 성공적으로 종료된 경우 파일 이름을 바꾸십시오"를 의미합니다 .

답변2

-i플래그가 없으면 모든 명령의 결과가 sed표준 출력에 기록됩니다.

이 예에서는 표준 출력을 다른 파일( )로 리디렉션합니다 /etc/nginx/sites-available/${domain}.conf.

답변3

sed파일에 직접 쓰는 대신 출력을 파일로 리디렉션해야 하는 이유를 묻는 것 같습니다 . 그렇다면 몇 가지 이유가 있습니다.

  1. 실제로 -i의 매개변수를 통해 이 작업을 수행 할 수 있습니다 sed.
  2. 이는 다른 프로그램과 통신하는 프로그램을 설계하는 일반적인 UNIX 철학을 따르지 않기 때문에 기본 동작이 아닙니다(https://en.wikipedia.org/wiki/Unix_philosophy).
    많은 UNIX 쉘 유틸리티의 기본 개념은 이들을 서로 연결하는 것입니다( foo | bar | baz). 이를 통해 각 단계 사이에 데이터를 디스크에 버퍼링하지 않고도 데이터에 대한 복잡한 처리를 수행할 수 있습니다.

관련 정보