슬래시가 포함될 수 있는 파일에서 처음 나타나는 패턴을 바꿉니다.

슬래시가 포함될 수 있는 파일에서 처음 나타나는 패턴을 바꿉니다.

감사해요이 링크난 어떻게 하는지 알아슬래시가 포함된 변수 전달하기sed 패턴으로:

sed "s~$var~replace~g" $file. / 대신 단일 바이트 문자를 사용하십시오.

감사해요이 다른 링크나도 알아 어떻게파일에서 처음 나타나는 패턴만 바꾸기(같은 줄에 있지 않음):

sed "0,/$var/s/$var/replacement/" filename 또는 sed 0,/$var/{s/$var/replacement/} filename

하지만 그렇게 하면 ( sed '0,~$var~s~$var~replacement~' filename 또는 0으로 시작하고 슬래시가 없는 다른 것) 오류가 발생합니다: unknown command: '0'.

이 둘을 어떻게 결합할 수 있나요? 아마도 awk나 Perl을 사용하거나...?

답변1

하지만:

sed "0,\~$var~s~$var~replacement~"

정규식 구분 기호를 변경하는 데 사용할 수 있습니다. sed일반적으로 코드(또는 다른 인터프리터) 코드에 변수 확장을 포함하는 것은 매우 현명하지 못한 일입니다.

우선, 이 구분 기호는 이스케이프해야 하는 유일한 문자가 아닙니다. 이는 모든 정규식 연산자에도 필요합니다.

그러나 더 중요한 것은 특히 GNU의 경우 sed이는 명령 주입 취약점입니다. 콘텐츠를 $var제어할 수 없는 경우 임의의 데이터를 eval.

예를 들면 다음과 같습니다.

$ var='^~s/.*/uname/e;#'
$ echo | sed "0,\~$var~s~$var~replacement~"
Linux

명령 uname이 실행되었으며 다행히 이번에는 무해했습니다.

GNU가 아닌 sed구현에서는 임의의 명령을 실행할 수 없지만 명령을 사용하여 모든 파일을 덮어쓸 수 있는데 w이는 실제로도 마찬가지입니다.

좀 더 정확한 방법은$var먼저 문제가 있는 문자를 탈출하세요:

NL='
'
case $var in
  (*"$NL"*)
    echo >&2 "Sorry, can't handle variables with newline characters"
    exit 1
esac
escaped_var=$(printf '%s\n' "$var" | sed 's:[][\/.^$*]:\\&:g')
# and then:
sed "0,/$escaped_var/s/$escaped_var/replacement/" < file

또 다른 방법은 다음을 사용하는 것입니다 perl.

var=$var perl -pe 's/\Q$ENV{var}\E/replacement/g && $n++ unless $n' < file

$var우리는 전달된 코드 내부의 내용을 확장하지 않고 perl(또 다른 명령 주입 취약점이 될 수 있음) 대신 perl해당 내용을 정규식 처리의 일부로 확장하도록 합니다( \Q...\E즉, 정규식 연산자가 특별하게 처리되지 않음을 의미).

개행 문자가 포함된 경우 $var끝에 하나만 있어야 일치가 가능합니다. 또는 -0777입력이 한 줄씩 처리되지 않고 단일 레코드로 처리되도록 이 옵션을 전달할 수 있습니다.

답변2

Stephane의 솔루션과 유사하게 perl" awk위험한" 보간을 보호하는 문제는 대안을 통해 피할 수 있습니다.

export pattern="anypattern" # or whatever shell quoting is needed
awk 'NR==1,$0~ENVIRON["pattern"] {sub(ENVIRON["pattern"],"replacement")} 1' input
# or gsub if you want multiple matches on the first line with any match

데이터가 (아마도) 크고 패턴이 (아마도) 비용이 많이 드는 경우, awk약간 다른 관용구와 일치하는 항목을 찾으면 불필요한 일치를 피할 수도 있습니다.

awk '!x&&$0~ENVIRON["pattern"] {sub(ENVIRON["pattern"],"replacement");x=1} 1' input
# ditto

알림: ( awk또는 sed) 실제 접두사가 &필요한 경우 (일반적으로 먼저 쉘에서 인용해야 하며 여기서는 에 있음 ), 마찬가지로 실제 접두사를 두 배로 늘립니다.&\''\

관련 정보