START
패턴으로 표시된 섹션 앞뒤에 잘못된 텍스트가 있는 파일 END
(각 특정 문자열은 한 번만 나타나며 같은 줄에 올바른 순서로 나타납니다). 나는 단지 START
와 사이의 부분에 대해 문자열 조작을 하고 싶습니다 .END
입력 예:
aomodi3hriq32| ¶³r 0q93aoiSTART_this_is_to_be_modified_ENDaqsdofuha23uru| ²23i ii3uhfia
oawpo3<9"§ A hSTART_this_also_needs_modification_ENDqa 032/a237(°1Q"§ >A_this_
START changeme ENDnot_this_modias
- 연산에 관한 한, sed
및 사이의 하위 문자열(및 하위 문자열만)은 내가 사용하는 것처럼 수정되어야 합니다.START
END
sed 's/_this_// ; s/modi/MODI/ ; y/as/45/'
출력 예:
aomodi3hriq32| ¶³r 0q93aoiSTARTi5_to_be_MODIfied_ENDaqsdofuha23uru| ²23i ii3uhfia
oawpo3<9"§ A hSTART4l5o_need5_MODIfic4tion_ENDqa 032/a237(°1Q"§ >A_this_
START ch4ngeme ENDnot_this_modias
awk
여러 값을 다른 위치에 설정할 수 없기 FS="START|END"
때문에 실패합니다 .OFS
중첩된 명령 대체 및 다른 구분 기호( ) 를 사용해 보았 으나 실패했으며, 명령 앞/뒤에 문자가 있어 명령을 엉망으로 만들 수 있다는 점도 sed
우려했습니다 (예: a ). ~
아이디어는 "내부" 하위 문자열만 선택하고 작업을 수행한 다음 이를 대체의 일부로 사용하는 것입니다.START
END
/
sed "s/^\(.*\)START.*END\(.*\)$/\1$(sed 's~^.*START~~
s~END.*~~
s~_this_~~
s~modi~MODI~
y~as~45~' infile)\2/" infile
나는 예를 들어 perl
....하지만 무엇이든 익숙하지 않습니다.
sed
REGEX 일치 하위 문자열 행에만 집합 작업을 적용할 수 있는 방법이 있습니까 ?
답변1
perl -CSD -ne '
if (my ($before, $between, $after) = /^(.*START)(.*)(END.*)/) {
s/_this_//, s/modi/MODI/, tr/as/45/ for $between;
print "$before$between$after\n";
} else { print; }' -- file
-CSD
UTF-8에서 입력을 디코딩하고 출력을 UTF-8로 인코딩합니다.$before
대신 및 를 사용하여 세 가지 변수 , 및 를 채울 수 있지만$between
더 나은 솔루션을 찾지 못했습니다.$after
/p
${^PREMATCH}
${^POSTMATCH}
if (my ($s) = /START(.*)END/p) { s/_this_//, s/modi/MODI/, tr/as/45/ for $s; print "${^PREMATCH}START${s}END${^POSTMATCH}"; } else { print; }
START...END 부분이 한 줄에서 반복될 수 있는 경우 각 줄을 반복해야 합니다.
for my $part (split /(START.*?END)/) {
if ($part =~ /^START.*END$/) {
s/_this_//, s/modi/MODI/, tr/as/45/ for $part;
}
print "$part";
}
답변2
기준을 사용 sed
하고 각 줄에 정확히 하나 START
와 하나의 END
하위 문자열이 포함되어 있다고 가정합니다(순서대로).
# Skip (pass through) lines that does not have START followed by END.
/.*START\(.*\)END.*/ !b
# Save the original line in the hold space.
h
# Remove the start and the end from the line.
# This leaves the bit of the line that we want to modify.
# (This reuses the previous regular expression.)
s//\1/
# Modify what's left.
s/_this_//
s/modi/MODI/
y/as/45/
# Append the original line from the hold space,
# with a newline as delimiter.
G
# Move the modified bit into the correct spot with a substitution,
# while deleting the old substring between START and END.
s/\(.*\)\n\(.*START\).*\(END.*\)/\2\1\3/
시험:
$ cat file
aomodi3hriq32| ¶³r 0q93aoiSTART_this_is_to_be_modified_ENDaqsdofuha23uru| ²23i ii3uhfia
oawpo3<9"§ A hSTART_this_also_needs_modification_ENDqa 032/a237(°1Q"§ >A_this_
START changeme ENDnot_this_modias
$ sed -f script file
aomodi3hriq32| ¶³r 0q93aoiSTARTi5_to_be_MODIfied_ENDaqsdofuha23uru| ²23i ii3uhfia
oawpo3<9"§ A hSTART4l5o_need5_MODIfic4tion_ENDqa 032/a237(°1Q"§ >A_this_
START ch4ngeme ENDnot_this_modias
인라인, 명령줄에서:
sed -e '/.*START\(.*\)END.*/!b' -e h -e 's//\1/' \
-e 's/_this_//' -e 's/modi/MODI/' -e 'y/as/45/' \
-e G -e 's/\(.*\)\n\(.*START\).*\(END.*\)/\2\1\3/' file
답변3
언제든지 자신만의 OFS를 여러 개 구축할 수 있습니다.
awk -v FS='START|END' -v OFS= -v map='_this_\r\rmodi\rMODI\ra\r4\rs\r5' '
BEGIN{ split(FS, mOFS, "|") }
{ n=split(map, tr, "\r"); for(i=1; i<n; i+=2) gsub(tr[i], tr[i+1], $2);
print $1, mOFS[1], $2, mOFS[2], $3
}' infile
gsub()의 첫 번째 인수는 정규식이므로 정의할 때 주의하세요.map=....
;오른쪽 매핑에는 &
역참조 \1
등과 같은 일부 특수 문자가 있어서는 안 됩니다. 그러나 매핑을 수동으로 작성할 때 특수 문자를 이스케이프하여 gsub()에 의해 독점적으로 해석되는 것을 방지할 수 있습니다.
CR을 사용하여 \r
지도를 분리하고 있습니다. 말씀하신 대로 입력 파일에 존재하지 않는 유일한 것입니다. 단, \0
Split() 및 awk의 다른 함수(또는 다른 프로그래밍에서는 작동하지 않습니다) 언어도 마찬가지), awk는 \0
문자열에 최대 하나만 있을 수 있다고 간주하기 때문입니다 . 따라서 각 왼쪽 정규식 tr[i]
(여기서는 문자열) 이 배열 tr[i+1]
의 다음 오른쪽 정규식 으로 대체됩니다 tr
.
이 접근 방식을 사용하면 각 쌍에 대해 여러 개의 gsub()를 작성하지 않아도 됩니다.
답변4
모든 Unix 시스템의 모든 쉘에서 awk를 사용하십시오.
$ cat tst.awk
match($0,/START.*END/) {
tgt = substr($0,RSTART+5,RLENGTH-8)
sub(/_this_/,"",tgt)
sub(/modi/,"MODI",tgt)
gsub(/a/,"4",tgt)
gsub(/s/,"5",tgt)
$0 = substr($0,1,RSTART+4) tgt substr($0,RSTART+RLENGTH-3)
}
{ print }
$ awk -f tst.awk file
aomodi3hriq32| ¶³r 0q93aoiSTARTi5_to_be_MODIfied_ENDaqsdofuha23uru| ²23i ii3uhfia
oawpo3<9"§ A hSTART4l5o_need5_MODIfic4tion_ENDqa 032/a237(°1Q"§ >A_this_
START ch4ngeme ENDnot_this_modias