‘abbc’문자열이 있고 바꾸고 싶다고 가정 해보십시오.
- ab-> 기원전
- bc-> ab
두 번 교체하려고하면 결과가 원하는 것이 아닙니다.
echo 'abbc' | sed 's/ab/bc/g;s/bc/ab/g'
abab
그렇다면 아래와 같이 대체 할 수있는 sed 명령은 무엇입니까?
echo abbc | sed SED_COMMAND
bcab
편집 : 실제로 텍스트에는 2 개 이상의 패턴이있을 수 있으며 필요한 교체 수를 알 수 없습니다. sed
스트림 편집기 라는 답변이 있었고 그 대체품은 탐욕스럽게 생각하기 때문에 스크립트 언어를 사용해야한다고 생각합니다.
답변
아마도 이런 식으로 뭔가 :
sed 's/ab/~~/g; s/bc/ab/g; s/~~/bc/g'
~
문자열에없는 문자로 바꿉니다 .
답변
나는 항상 “-e”와 함께 여러 문장을 사용한다
$ sed -e 's:AND:\n&:g' -e 's:GROUP BY:\n&:g' -e 's:UNION:\n&:g' -e 's:FROM:\n&:g' file > readable.sql
이것은 모든 AND, GROUP BY, UNION 및 FROM 앞에 ‘\ n’을 추가하는 반면 ‘&’는 일치하는 문자열을 의미하고 ‘\ n &’은 일치하는 문자열을 ‘\ n’앞에 ‘\ n’으로 바꾸려는 것을 의미합니다 ‘
답변
다음은 값이 재사용되는 방법을 확인하지 않고 여러 검색 및 바꾸기 쌍에 작동 하는 ooga의 답변 변형입니다 .
sed -i '
s/\bAB\b/________BC________/g
s/\bBC\b/________CD________/g
s/________//g
' path_to_your_files/*.txt
예를 들면 다음과 같습니다.
전에:
some text AB some more text "BC" and more text.
후:
some text BC some more text "CD" and more text.
\b
단어 경계를 나타내 ________
므로 검색을 방해 하지 않습니다 (우분투에서 GNU sed 4.2.2를 사용하고 있습니다). 단어 경계 검색을 사용하지 않으면이 기술이 작동하지 않을 수 있습니다.
또한 명령을 제거 하고 명령 끝에 s/________//g
추가 하는 것과 동일한 결과를 제공 && sed -i 's/________//g' path_to_your_files/*.txt
하지만 경로를 두 번 지정할 필요는 없습니다.
jthill이 제안한 것처럼 파일에 null이 나타나지 않는다는 것을 알고 있다면 대신 사용 \x0
하거나 _\x0_
대신 사용할 ________
수 있습니다 .
답변
sed
스트림 편집기입니다. 탐욕스럽게 검색하고 교체합니다. 요청한 것을 수행하는 유일한 방법은 중간 대체 패턴을 사용하고 결국 다시 변경하는 것입니다.
echo 'abcd' | sed -e 's/ab/xy/;s/cd/ab/;s/xy/cd/'
답변
이것은 당신을 위해 일할 수 있습니다 (GNU sed) :
sed -r '1{x;s/^/:abbc:bcab/;x};G;s/^/\n/;:a;/\n\n/{P;d};s/\n(ab|bc)(.*\n.*:(\1)([^:]*))/\4\n\2/;ta;s/\n(.)/\1\n/;ta' file
이 테이블은 보류 공간 (HS)에서 준비된 후 각 행에 추가되는 찾아보기 테이블을 사용합니다. 고유 한 마커 (이 경우 \n
)는 줄의 시작 부분에 추가되며 줄 길이 전체에서 검색을 범프하는 방법으로 사용됩니다. 마커가 라인의 끝에 도달하면 프로세스가 완료되고 조회 테이블과 마커가 삭제됩니다.
NB 룩업 테이블은 시작시 준비되며 :
대체 문자열과 충돌하지 않도록 선택된 두 번째 고유 마커 (이 경우 )를 준비합니다.
일부 의견 :
sed -r '
# initialize hold with :abbc:bcab
1 {
x
s/^/:abbc:bcab/
x
}
G # append hold to patt (after a \n)
s/^/\n/ # prepend a \n
:a
/\n\n/ {
P # print patt up to first \n
d # delete patt & start next cycle
}
s/\n(ab|bc)(.*\n.*:(\1)([^:]*))/\4\n\2/
ta # goto a if sub occurred
s/\n(.)/\1\n/ # move one char past the first \n
ta # goto a if sub occurred
'
테이블은 다음과 같이 작동합니다.
** ** replacement
:abbc:bcab
** ** pattern
답변
단일 패턴 발생에 대한보다 간단한 접근법 일 수 있습니다. 다음과 같이 시도 할 수 있습니다. echo ‘abbc’| sed ‘s / ab / bc /; s / bc / ab / 2’
내 출력 :
~# echo 'abbc' | sed 's/ab/bc/;s/bc/ab/2'
bcab
여러 번 패턴이 나타나는 경우 :
sed 's/\(ab\)\(bc\)/\2\1/g'
예
~# cat try.txt
abbc abbc abbc
bcab abbc bcab
abbc abbc bcab
~# sed 's/\(ab\)\(bc\)/\2\1/g' try.txt
bcab bcab bcab
bcab bcab bcab
bcab bcab bcab
도움이 되었기를 바랍니다 !!
답변
Tcl에는이 기능이 내장 되어 있습니다
$ tclsh
% string map {ab bc bc ab} abbc
bcab
이것은 현재 위치에서 시작하는 문자열 비교를 수행하여 문자열을 한 번에 한 문자 씩 걷는 것으로 작동합니다.
펄에서 :
perl -E '
sub string_map {
my ($str, %map) = @_;
my $i = 0;
while ($i < length $str) {
KEYS:
for my $key (keys %map) {
if (substr($str, $i, length $key) eq $key) {
substr($str, $i, length $key) = $map{$key};
$i += length($map{$key}) - 1;
last KEYS;
}
}
$i++;
}
return $str;
}
say string_map("abbc", "ab"=>"bc", "bc"=>"ab");
'
bcab