sed 대체의 LHS 및 RHS에서 변수를 사용하려면 어떻게해야합니까?


60

나하고 싶어:

cat update_via_sed.sh | sed 's/old_name/new_name/' > new_update_via_sed.sh

내 프로그램에서.

그러나 나는 변수를 사용하고 싶다.

old_run='old_name_952'
new_run='old_name_953'

나는 그것들을 사용하려고 시도했지만 대체가 발생하지 않습니다 (오류 없음). 나는 시도했다 :

cat update_via_sed.sh | sed 's/old_run/new_run/'
cat update_via_sed.sh | sed 's/$old_run/$new_run/'
cat update_via_sed.sh | sed 's/${old_run}/${new_run}/'

2
명령 인수에서 매개 변수 사용 에서 답을 찾을 수 있습니다 .
manatwork

답변:


44

당신은 할 수 있습니다 :

sed "s/$old_run/$new_run/" < infile > outfile

하지만 조심 $old_run정규 표현식으로 간주 될 수와 같은 변수가 포함되어 있으므로 특수 문자, /또는 .해야 이스케이프 . 마찬가지로에서 $new_run&\문자는 특별하게 취급 될 필요가 당신은 탈출해야합니다 /거기에와 줄 바꿈 문자를.

의 내용이있는 경우 $old_run또는 $new_run당신의 통제하에 있지, 그것은 탈출 것을 수행하는 것이 중요합니다, 또는 그렇지 않으면 그 코드는 코드 주입 취약점에 달한다 .


3
sed params에서 작은 따옴표를 사용하고 큰 따옴표로 전환했으며 파일이 작동했습니다. 대박.
Aakash

그것만으로는 sed정규 표현식을 사용하지 않지만 그렇지 sed -E않습니까?
Kiwy

@ 키위. -e지정하는 것입니다 sed 전자 xpression을 , 그래서 당신이 (같이 하나 이상을 전달할 수 있습니다 sed -e exp1 -e exp2) 또는 파일과 표현의 조합 ( sed -f file -e exp). -E일부 구현에서는 sed에게 BRE 대신 ERE를 사용하도록 지시하는 것이 혼동 될 수 있습니다 .
Stéphane Chazelas

나는 잘못 입력했지만 OK, -E정규 정규식이 아닌 확장 정규식 만 마스터 하지 않고 sed를 사용하여 많은 문제가 발생하는 이유를 설명 합니다. 설명해 주셔서 감사합니다.
Kiwy

@Kiwy, 더 일반적인 표현식 구문에 대한 일부 구현에서 지원되는 추가 옵션에 대해서는 연결된 Q & A 도 참조하십시오 sed.
Stéphane Chazelas

31

이것은 효과가 있었다 :

cat update_via_sed.sh | sed 's/'"$old_run"'/'"$new_run"'/'

동일한 파일을 '재사용'하기 위해 비슷한 접근 방식을 원하는 사람에게 실제로 이것을 사용합니다.

cat update_via_sed.sh | sed 's/'"$old_run"'/'"$new_run"'/' > new_update; mv -f new_update update_via_sed.sh

위의 새 파일을 만든 다음 새 파일의 이름을 현재 파일로 바꾸는 것보다 현재 파일을 삭제합니다.


4
특별한 문자가 없다면 고양이, mv 또는 추가 ''가 필요하지 않습니다. 그렇습니다 sed -i s/"$old"/"$new"/ update_via_sed.sh. 그러나이 값은 이전 값과 새 값으로 작동하지 않습니다. 예를 들어 $ old는 여전히 검색이고 일부 문자에는 특별한 의미가있는 $ new 대체 패턴이므로 / etc를 포함해서는 안됩니다.
frostschutz

1
sed -i "s/$old/$new/"위의 예방 조치로도 괜찮습니다. sed일반적으로 s명령 뒤에 구분 기호를 첫 번째 문자로 간주합니다. 즉, 변수에 슬래시가 /있지만 ( @) 에서 말할 수없는 경우 "s @ $ old @ $ new @"를 사용할 수 있습니다.
peterph

22

큰 따옴표 (작은 따옴표가 아님) 인 한 sed에서 변수를 사용할 수 있습니다.

sed "s/$var/r_str/g" file_name >new_file

/변수에 슬래시 ( ) 가 있으면 아래처럼 다른 구분 기호를 사용하십시오

sed "s|$var|r_str|g" file_name >new_file

1
큰 따옴표를 사용해야하는 경우 +1 그게 내 문제 야
speckledcarp

1
정확히 내가 무엇의 사용을 포함, 찾고 있던 |내 경우 등이있다, 그래서 변수는 경로가 포함되어 /거기에
yorch

어떤 이유로 파이프 |는 MacOS 10.14에서 나를 위해 일했지만 다른 분리기는 좋아 @하거나 #그렇지 않습니다. 내 환경 변수에도 슬래시가있었습니다.
davidenke

21

'in-place'sed (-i 플래그 사용)가 답입니다. peterph에게 감사합니다.

sed -i "s@$old@$new@" file

2
따옴표가 잘못되었습니다. 따옴표는 변수 주위에 없어야합니다 (어떻게 s@든 쉘에 특별하지는 않습니다). 가장 좋은 것은 모든 것을 따옴표 안에 넣는 것 sed -i "s@$old@$new@" file입니다. 그 참고 -i표준 아닙니다 sed옵션을 선택합니다.
Stéphane Chazelas

$이 명령에서 어떻게 벗어날 수 있습니까 ? 마찬가지로 $xxx전체 변수 값으로 변경하려고 합니다 $JAVA_HOME. 나는 노력 sed -i "s@\$xxx@$JAVA_HOME@" file하지만 오류가 말한다no previous regular expression
hakunami

3

man bash 작은 따옴표에 대해 이것을 제공합니다

작은 따옴표로 문자를 묶으면 따옴표 안에 각 문자의 리터럴 값이 유지됩니다. 백 슬래시가 앞에 있어도 작은 따옴표 사이에는 작은 따옴표가 없을 수 있습니다.

bash는 명령 줄에 입력 한 내용을 해석하고 해석하여 결과를 전송 될 프로그램으로 보냅니다.이 경우 sed 's/$old_run/$new_run/'bash 를 사용하면을 먼저보고 변수에 sed실행 파일로 인식 $PATH. sed실행 파일은 입력이 필요합니다. 배시는 입력을 찾아서 찾습니다 's/$old_run/$new_run/'. 작은 따옴표는 bash가 내용을 해석하지 않고 그대로 전달하지 말라고 말합니다. 따라서 bash는 sed로 전달합니다. $줄 끝에서만 발생할 수 있으므로 Sed에서 오류 가 발생합니다.

대신 큰 따옴표, 즉 "s/$old_run/$new_run/"bash를 사용하면 bash는 이것을보고 $old_run변수 이름으로 해석 하고 대체합니다 (이 단계를 변수 확장이라고합니다). 이것이 실제로 우리가 요구 한 것입니다.

그러나 큰 따옴표는 bash에서 먼저 해석 한 다음 sed에 제공되므로주의해야합니다. 따라서`와 같은 일부 기호는 사용하기 전에 이스케이프해야합니다.


1

플립 패인의 위험이 있습니다 perl.

무엇보다도 'sed style'작업을 수행하는 데 능숙하지만 더 완전한 기능을 갖춘 프로그래밍 기능입니다.

그것은 보이는 당신의 예처럼, 당신이있어 무엇을 실제로 일을하려고하는 숫자를 증가한다.

그래서 어떻습니까 :

#!/usr/bin/env perl
use strict;
use warnings 'all'; 

while ( <DATA> ) {
    s/old_name_(\d+)/"old_name_".($1+1)/e;
    print;
}

__DATA__
old_name_932

또는 하나의 라이너-sed 스타일로 :

perl -pe 's/old_name_(\d+)/"old_name_".($1+1)/e'

1
$ echo $d1 | sed -i 's/zkserver1/'${d1}'/g' deva_file
sed: -e expression #1, char 26: unterminated `s' command 

에서 $d1나는 값을 저장하고

변수의 값을 바꿀 수 없으므로 다음 명령을 시도했습니다.

echo $d1 | sed -i 's/zkserver1/'"${d1}"'/g' deva_file

에 큰 따옴표가 없습니다 "${d1}". 오류입니다.


-2

가정 $old_run되고 $new_run이미 설정되어 있습니다.

cat update_via_sed.sh | eval $(print "sed 's/$old_run/$new_run/g'")

화면에 변경 사항이 표시됩니다. 필요한 경우 출력을 파일로 리디렉션 할 수 있습니다.


-2

sed에서 변수를 사용하려면 큰 따옴표 ""를 사용하여 변수를 사용중인 패턴으로 묶으십시오. 예 : a = "Hi"패턴에 변수 'a'를 추가하려면 다음을 사용할 수 있습니다. sed -n "1, / pattern"$ {a} "pattern / p"filename


2
여기서 확장 $a은 따옴표로 묶여 있지 않습니다. 즉, 값에 공백이 있으면 셸에서 단어 분할이 호출됩니다.
Kusalananda

-2

Perl을 사용할 수도 있습니다 :

perl -pi -e ""s/$val1/$val2/g"" file

값에 공백이있을 수있는 변수를 고려하십시오. Perl 표현식 ( "") 주위의 빈 문자열 은 아무 것도 수행하지 않습니다.
Kusalananda

-2

줄을 끊다

나쁜 => 리눅스는 $ old_run 문자열을 참조하십시오 :

sed 's/$old_run/$new_run/'

good => linux 변수 $ old_run을보십시오 :

sed 's/'$old_run'/'$new_run'/'

1
그리고 경우 $old_run또는 $new_run공백이 포함?
Kusalananda
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.