파일에 있는 문자열을 다른 문자열로 바꾸고 싶지만 둘 다 및 .
같은 특수 문자(이 경우 문자)가 있습니다 .1.0
2.0
현재 사용되는 명령은 다음과 같습니다.
sed -i 's/1\.0/2\.0/g' /home/user1/file1.txt
1.0
and 가 2.0
변수 and 에 저장되면 어떻게 $i
될까요 $j
? i
가치는 어디에 있습니까 1.0
? j
가치는 무엇 2.0
이며 무엇 으로 i
바꿀 수 있습니까 j
?
답변1
이를 사용하여 sed
문제를 해결할 수 있습니다.
printf '%s\n' "$i" "$j" |
sed 's/[]\$*&/.^[]/\\&/g;H;$!d
x;y|\n|/|;s|.*|s&/g|' |
sed -f - /path/to/infile
따라서 이 s///
교체는 입력의 모든 BRE 메타 문자를 이스케이프합니다.
s/[]\$*&/.^[]/\\&/g
...각각 앞에 백슬래시를 붙입니다. 그런 다음 첫 번째 항목은 sed
첫 번째 줄 $i
의 복사본을 저장합니다 . H
이전 공간 에 ewline 문자를 추가하여 저장합니다 \n
. $i
그런 다음 해당 행은 마지막 행이 아니기 d
때문에 삭제 됩니다. 다음 줄(이 줄)은 마지막 줄이기도 합니다. 첫 번째 줄과 동일한 처리를 받은 후에는 다음과 같습니다.!
$
$j
아니요 d
선택된. 대신, x
보유 버퍼와 모드 버퍼를 변경하고 연결 결과에 따라 작동합니다. 이 시점에서 패턴 공간은 다음과 같습니다.
\n1\.0\n2\.0
...그래서 우리는 y///
모든 \n
줄을 /
슬래시 로 변환하고 s///
모든 것을 패턴 공간 자체와 접두사 및 접미사로 대체하여 다음을 얻습니다..*
&
s
/g
s/1\.0/2\.0/g
그런 다음 stdin을 스크립트로 sed
읽는 두 번째 파일에 자동으로 인쇄됩니다 . -f -
첫 번째 작업이 sed
완료되고 파이프 사이가 닫히면 두 번째 작업이 sed
적용되기 시작합니다...
s/1\.0/2\.0/g
...여기에 있는 입력 파일의 각 줄 이름을 지정합니다 /path/to/infile
.
나는 다음과 같이 파일을 작성했습니다.
printf '%04s%04s%04s%04s\n' \
0 0 -1 0 1 0 0 0 0 -1\
0 0 1.5 2.0 1.0 0 >/tmp/temp
이것은 나에게 다음과 같은 것을 제공합니다 ...
0 0 -1 0
1 0 0 0
0 -1 0 0
1.5 2.0 1.0 0
그런 다음 다른 버전의 스크립트를 작성했습니다. 예를 들면 다음과 같습니다.
ii=0.0
for i in 1.0 2.0 3.0 4.0
do str2=$i
printf '\033[41m## %s \033[0m\n' \
"str2 = $str2" "$ii $str2"
printf %s\\n "$ii" "$str2"
ii=$str2
done |
sed ' s/[]\$^&*./[]/\\&/g;H;x
s|^\(\n\)\(.*\)\n\(.*\)\n\(.*\)\n\(.*\)|\
bs\5\1:i\5\1i\\\1\2\\\1\3\1:s\5\1s/\4/\5/gp;ti\5|p
s|||;h;d' |
sed -f - /tmp/temp
문자열을 생성하기 위해 셸만 사용하지만 sed
모든 데이터 처리가 수행되도록 허용합니다. sed
두 개가 호출 되더라도 각각은 한 번만 호출됩니다.
실행하면 결과는 다음과 같습니다.
0 0 -1 0
1 0 0 0
0 -1 0 0
1.5 2.0 2.0 0
## str2 = 2.0
## 1.0 2.0
1.5 3.0 3.0 0
## str2 = 3.0
## 2.0 3.0
1.5 4.0 4.0 0
## str2 = 4.0
## 3.0 4.0
1.5 4.0 4.0 0
#
예상대로 로 시작하는 줄은 빨간색으로 표시됩니다. sed
교체가 성공한 경우에만 기록 됩니다 . s///
두 번째 스크립트를 위해 작성된 첫 번째 스크립트는 sed
다음과 같습니다.
bs1\.0
:i1\.0
i\
[41m## str2 = 1\.0 [0m\
[41m## 0\.0 1\.0 [0m
:s1\.0
s/0\.0/1\.0/gp;ti1\.0
bs2\.0
:i2\.0
i\
[41m## str2 = 2\.0 [0m\
[41m## 1\.0 2\.0 [0m
:s2\.0
s/1\.0/2\.0/gp;ti2\.0
bs3\.0
:i3\.0
i\
[41m## str2 = 3\.0 [0m\
[41m## 2\.0 3\.0 [0m
:s3\.0
s/2\.0/3\.0/gp;ti3\.0
bs4\.0
:i4\.0
i\
[41m## str2 = 4\.0 [0m\
[41m## 3\.0 4\.0 [0m
:s4\.0
s/3\.0/4\.0/gp;ti4\.0
문자열이 이스케이프되지 않은 것처럼 보이지만 [
이는 단지 내 터미널이 출력에 미치는 영향일 뿐입니다. 결국 바로 뒤에 오는 char을 먹게 됩니다 \033
. 두 번째 스크립트가 sed
스크립트를 수신하면 입력은 다음과 같지만 \033\[...
stdout에 삽입하는 출력은 i
다음과 같습니다.\033[...
답변2
이것을 시도하십시오: 모두 탈출하십시오. 모두 .
다음으로 교체\.
str1="$( echo -n $i | sed 's/\./\\\./g' )"
str2에 대해서도 동일한 작업을 반복합니다.$j. 그런 다음 다음으로 교체하십시오.
sed "s/$str1/$str2/g"