sed는 다른 일치 항목의 첫 번째 일치 항목을 변경합니다.

sed는 다른 일치 항목의 첫 번째 일치 항목을 변경합니다.

텍스트 파일의 특정 그룹의 합계를 변경하고 싶습니다 PATH.LOC_NAME

예를 들어:

[a]
PATH=/tmp
SUR=Y
LOC_NAME=USA
[b]
PATH=/tmp
SUR=N
LOC_NAME=UK

따라서 검색하려면 [b]그 이후의 첫 번째 일치 항목만 변경하고 싶습니다(다음 대신 다음 항목 이후 [*]).

sed -i '/PATH/c\PATH=\/u01'
sed -i '/LOC_NAME/c\LOC_NAME=RUS'

답변1

당신은 매우 가깝습니다!

다음을 추가할 수 있습니다.주소 범위변경해야 할 부분에 대해. 블록 외부의 [b]모든 항목을 변경하지 않고 시작하는 줄부터 다음 줄까지 유지하려면 [두 표현식 사이에 쉼표가 있는 주소 범위를 선택하고(이제 변경하려는 블록만 있음) 역순으로 !( 이제 변경하려는 블록만 있음) 다른 모든 것을 얻습니다) 명령을 사용하여 b스크립트 끝으로 분기합니다. 따라서 각 후속 명령은 해당 범위의 행에만 영향을 미칩니다.

sed -i '/^\[b\]$/,/^\[/!b
  /PATH/c\PATH=\/u01
  /LOC_NAME/c\LOC_NAME=RUS'

물론 {commands;...;}역방향 및 분기 대신 블록을 사용하여 역방향이 아닌 매칭을 수행할 수도 있지만 이는 가독성이 떨어진다고 생각합니다.

변수의 단어를 식별자로 사용하려면 다음을 수행할 수 있습니다.

ID=foo
sed -i '/^\['$ID'\]$/,/^\[/!b
  /PATH/c\PATH=\/u01
  /LOC_NAME/c\LOC_NAME=RUS'

답변2

awkPerl을 사용하는 것이 더 쉬울 수도 있습니다.

$ cat input
[a]
PATH=/tmp
[b]
PATH=/tmp
OTHERPATH=/somedir
[c]
PATH=/tmp

$ gr="[b]"
$ repl=/u01
$ awk -vgr="$gr" -vrepl="$repl"  '/^\[.*\]$/ { group=$0 } group == gr && /^PATH=/ { $0 = "PATH=" repl } 1' input
[a]
PATH=/tmp
[b]
PATH=/u01
OTHERPATH=/somedir
[c]
PATH=/tmp

$ gr=b
$ repl=/u01
$ gr=$gr repl=$repl perl -pe '$group = $1 if /^\[(.*)\]$/; s,^PATH=.*,PATH=$ENV{repl}, if $group eq $ENV{gr}' < input
[same output]

아이디어는 가 있는 행을 찾아 [something]이름을 기록한 다음 해당 행에 대해 조건부 교체를 수행하는 것입니다. (awk 버전은 괄호로 그룹 이름을 사용하는 반면 Perl 버전은 그렇지 않습니다. 후자는 더 예쁘지만 awk에서는 Perl만큼 단순하지 않습니다. Perl 버전은 환경을 통해 변수를 가져오므로 다음을 수행해야 합니다 export gr. repl, 또는 동일한 명령줄에서 할당).

키가 인 경우에만 교체하도록 수정했지만 PATH여전히 PATH동일한 제목(첫 번째 제목뿐만 아니라) [b]아래의 모든 s를 변경하지만 두 개 이상을 가질 수 있는지 확실하지 않습니다.

관련 정보