sed 스크립트의 각 줄에서 처음 5개의 공백 문자를 바꾸고 싶습니다. 이것이 내가 지금까지 가지고 있는 것입니다
sed -e "s/ /;/" -e "s/ /;/" -e "s/ /;/" -e "s/ /;/" -e "s/ /;/" myfile
더 좋은 방법이 있나요?
그런데 저는 Solaris sed를 사용하고 있습니다. 그것이 차이를 가져오는지는 모르겠습니다.
답변1
귀하의 질문을 읽으면서 적어도 GNU Sed(아마도 Solaris에 있는 것이 아닐 수도 있음)가원하는 반대 기능:
g: 첫 번째 항목뿐만 아니라 정규식과 일치하는 모든 항목에 대체를 적용합니다.
number: 정규 표현식의 숫자 번째 일치 항목만 바꿉니다.
Note: the posix standard does not specify what should happen when
현재 sed 구현 간에 널리 합의된 의미가 없는 g 및 숫자 수정자를 혼합하고 있습니다. GNU sed의 경우 상호 작용은 다음과 같이 정의됩니다. 세 번째 일치 이전의 일치 항목을 무시한 다음 세 번째 일치 이후의 모든 일치 항목을 일치시키고 교체합니다.
그래서 대신:
hmontoliu@ulises:/tmp/wb$ echo one two three four five six seven | sed 's/ /;/g5'
one two three four five;six;seven
다음을 수행하여 원하는 것을 달성하기 위한 보다 간결한 명령을 얻을 수 있습니다.
hmontoliu@ulises:/tmp/wb$ echo one two three four five six seven | sed -e 's/ /;/g' -e 's/;/ /6g'
one;two;three;four;five;six seven
Solaris 구현에 이 기능이 있는지 알려주십시오.
화타이
답변2
반복적인 sed 저글링을 수행하는 것보다 기본 아이디어를 고수하는 것이 더 쉽습니다. 아마도 간단한 for 루프를 사용하여 패턴을 구축하면 사용하기가 더 쉬워질 것입니다.
pat=; for ((i=1; i<=5; i++)) ;do pat="$pat s/ /;/;"; done
sed -e "$pat" myfile
아니면 여러 -e
표현식 옵션을 삭제하고 ;
표현식 구분 기호로 모두 그룹화하면 됩니다.
sed -e "s/ /;/; s/ /;/; s/ /;/; s/ /;/; s/ /;/" myfile
이건 sed-오직일반적으로 귀찮게 하지 않을 버전이지만 대체 항목을 원하는 만큼 지정할 수 있습니다. (통과하다 {5}
)...
sed -nre ':check;G;/^.*\nx{5}$/{b print};s/^(.*)\n.*$/\1/;s/ /;/;t inc-tally;:print;P;x;s/.*//;x;b;:inc-tally;x;s/(.*)/\1x/;x;b check' myfile
~ 위에한 줄(?)조금 무섭기 때문에 여기에 sed 스크립트 파일을 통해 호출되는 구조화된 코드가 있습니다.sed -nrf "$fsed" myfile
:check ## check the tally
G ## pattern+=nl+hold
/^.*\nx{5}$/{ ## we have the full complement of replacements
b print ## branch to print (and continue)
} ##
s/^(.*)\n.*$/\1/ ##
s/ /;/ ## change one space (if one is present)
t inc-tally ## branch_on_substitute
:print ## no more spaces to change
P ## pattern_first_line_print
x;s/.*//;x ## kill the accumulated tally chars in hold
b ## branch to end of proc (continue)
:inc-tally ##
x ## swap_pattern_and_hold
s/(.*)/\1x/ ##
x ## swap_pattern_and_hold
b check ## branch_unconditional