슬래시가 포함 된 변수를 sed에 전달하는 방법


100

슬래시를 포함하는 변수를 패턴으로 sed어떻게 전달 합니까?

예를 들어 다음 변수가있는 경우 :

var="/Users/Documents/name/file"

나는 그것을 다음과 sed같이 전달하고 싶다 .

sed "s/$var/replace/g" "$file"

그러나 오류가 발생합니다. 문제를 어떻게 피할 수 있습니까?

답변:


193

sed모든 구분 기호 ( 제어 문자 포함) 를 사용할 수 있도록 대체 정규식 구분 기호 를 사용합니다 .

sed "s~$var~replace~g" $file

2
작동하지 않습니다. 나는 sed -i "s ~ blah ~ $ var ~ g file"을 시도하고 "sed -e expression # 1, char 70 : unterminated`s 'command"를 얻습니다. 범인이 $ var의 슬래시임을 확인했습니다. 이에 대한이 솔루션의 변형은 어디에나 있으며 작동하지 않습니다. sed가 최근에 업데이트 되었습니까? Ubuntu 14.04.4 LTS의 v4.2.2에 있습니다.
Paul Ericson

즉의 값에 따라 달라집니다$var
anubhava

1
@PaulEricson이 관찰 한대로 ~와 함께 작동하지 않지만 |
Kenny Ho

1
마지막으로 "~"(g 후) 적어도 AWS 아마존 리눅스, 필요하지 않을 것 같다 (CentOS는 기준)
사울 마르티네스 Vidals

1
내 하루를 구했습니다
user7131571

62

순수한 bash 대답 : 매개 변수 확장 을 사용하여 변수의 슬래시를 백 슬래시로 이스케이프하십시오.

var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file

1
어떤 문자에 변수가 포함되어 있는지 항상 알 수 없기 때문에 이것은 좋은 방법입니다. 따라서 의심스러운 경우 sed 구분 기호를 항상 이스케이프 할 수 있습니다. 예를 들어 : sed "s : $ {var // : / \\ :} : replace : g"$ file
Stephane L

아름다운. 내 이름 변경 스크립트를 훨씬 깔끔하게 만들었습니다.
Cloud

오늘 아름다운 것을 배웠습니다. 감사합니다. 받아 들여진 대답이어야합니다.
Steve Kehlet

6
여기에서 사용되는 패턴에 대한 몇 가지 명확성 : ${parameter/pattern/string}. 따라서이 경우 매개 변수는 var, 패턴은 /\/, 문자열은 \\/입니다. 패턴이로 시작하기 때문에 패턴의 모든 인스턴스가 대체됩니다 /.
Josh

1
@josh이므로 패턴의 선행 슬래시는 실제로 대체 할 패턴의 일부가 아닙니다.
glenn jackman

32

이를 수행하는 또 다른 방법은 anubhava의 대답보다 추악하지만 var다른 sed명령 을 사용하여 모든 백 슬래시를 이스케이프하는 것입니다 .

var=$(echo "$var" | sed 's/\//\\\//g')

그러면 작동합니다.

sed "s/$var/replace/g" $file

12

/in sed를 구분 기호로 사용 하면 대체 될 때 변수의 슬래시와 충돌하므로 오류가 발생합니다. 이를 피하는 한 가지 방법은 해당 변수에있는 모든 문자에서 고유 한 다른 구분 기호를 사용하는 것입니다.

var="/Users/Documents/name/file"

상황에 맞는 옥토 토프 캐릭터 (또는 /사용하기 쉽지 않은 다른 캐릭터 )를 사용할 수 있습니다.

sed "s#$var#replace#g" 

또는

sed 's#$'$var'#replace#g'

변수에 공백이 없을 때 적합합니다.

또는

sed 's#$"'$var'"#replace#g'

셸이 특수 셸 문자로 간주 될 수있는 모든 문자를 셸에 끼울 수있는 전체 명령을 큰 따옴표로 묶는 것과 비교할 때만 해당 변수에있는 모든 것을 대체하는 데 관심이 있으므로 위의 내용을 사용하는 것이 현명합니다.


작동하지 않습니다. 나는 sed -i "s ~ blah ~ $ var ~ g file"을 시도하고 "sed -e expression # 1, char 70 : unterminated`s 'command"를 얻습니다. 범인이 $ var의 슬래시임을 확인했습니다. 이에 대한이 솔루션의 변형은 어디에나 있으며 작동하지 않습니다. sed가 최근에 업데이트 되었습니까? Ubuntu 14.04.4 LTS의 v4.2.2에 있습니다.
Paul Ericson

@PaulEricson 사용 가능한 Ubuntu에서 이것을 재현 할 수 없습니다. 당신이 경우 $var포함 ~, 당신은 분명히 다른 구분 기호를 선택해야합니다. "종결되지 않은"오류 $var는 새 줄이 포함 된 것처럼 들립니다 . 값의 모든 개행 문자를 백 슬래시로 이스케이프 처리하여 수정할 수 있지만 전적으로 이식 가능하다고 생각하지 않습니다. 이것은 대체로 값의 슬래시 문제와 관련이 없습니다.
tripleee

@PaulEricson 오 그리고 당신의 인용문이 정확하지 않습니다. 따옴표 안에 파일 이름이 있으면 안됩니다. sed -i "s~blah~$var~g" file실제 sed스크립트 를 따옴표로 묶습니다 .
tripleee

5

이것은 오래된 질문이지만 여기에 대한 답변 중 어느 것도 작업 s/from/to/에 대해 자세히 설명하지 않습니다.

sed진술 의 일반적인 형식은 다음과 같습니다 .

*address* *action*

여기서 address 는 정규식 범위 또는 줄 번호 범위 일 수 있습니다 (또는 비어있는 경우 작업 이 모든 입력 줄에 적용됨). 예를 들어

sed '1,4d' file

라인 1부터 4까지 삭제합니다 ( 주소 는 라인 번호 범위 1,4이고 작업d삭제 명령입니다). 과

sed '/ick/,$s/foo/bar/' file

처음 나타나는 대체 할 foo과이 bar정규 표현식에 제 매치 라인 사이에 ick파일 끝에합니다 ( 어드레스 범위 인 /ick/,$상기 액션 은 IS s대체 명령 s/foo/bar/).

이 컨텍스트 ick에서 변수에서 온 경우 다음을 수행 할 수 있습니다.

sed "/$variable/,\$s/foo/bar/"

(단일 대신 큰 따옴표를 사용하여 쉘이 변수를 보간 할 수 있고 큰 따옴표 안에 리터럴 달러 기호를 따옴표로 묶어야 함) 변수에 슬래시가 포함되어 있으면 구문 오류가 발생합니다. (쉘은 변수를 확장 한 다음 결과 문자열을에 전달합니다 sed. 따라서 sed리터럴 텍스트 만 볼 수 있습니다. 쉘의 변수에 대한 개념이 없습니다.)

해결 방법은 다른 구분 기호를 사용하는 것입니다 (분명히 변수 값에 나타날 수없는 문자를 사용할 수 있어야하는 경우). 그러나 s%foo%bar%경우 와 달리 다른 구분 기호를 사용하려면 구분 기호 앞에 백 슬래시가 필요합니다. 기본값보다 구분 기호 /:

sed "\\%$variable%,\$s/foo/bar/" file

(작은 따옴표 안에는 백 슬래시 하나로 충분합니다.) 또는 값의 모든 슬래시를 개별적으로 이스케이프 할 수 있습니다. 이 특정 구문은 Bash 전용입니다.

sed "/${variable//\//\\/}/,\$s/foo/bar/" file

또는 다른 셸을 사용하는 경우

escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file

명확성을 $variable위해 문자열 이 포함 된 경우 1/2위 명령은 다음과 같습니다.

sed '\%1/2%,$s/foo/bar/' file

첫 번째 경우에는

sed '/1\/2/,$s/foo/bar/' file

두 번째.


4

Perl을 사용하십시오. 여기서 변수는 확장 매크로가 아니라 일급 시민입니다.

var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
  • -p 입력 한 줄을 한 줄씩 읽고 처리 후 줄을 인쇄합니다.
  • \Q다음 문자열의 모든 메타 문자를 따옴표로 묶습니다 (여기에 제시된 값에는 필요하지 않지만 값에 포함 된 경우 필요 [하거나 정규 표현식에 특수한 다른 값).

Stack Exchange에서 수십 개의 "sed 표현식에서 변수 사용"질문에 대한 일반적으로 유용한 유일한 답변입니다. 다른 모든 것은 효과적으로 "sed에 특별한 것은 무엇이든 이스케이프"하는 것입니다. 이것은 변수와 sed의 가변성을 고려할 때 사실상 쓸모가 없습니다.
Heath Raftery
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.