파일의 문자열을 변수에 저장된 다른 파일의 문자열로 바꿉니다.

파일의 문자열을 변수에 저장된 다른 파일의 문자열로 바꿉니다.

파일에 있는 문자열을 다른 문자열로 바꾸고 싶지만 둘 다 및 .같은 특수 문자(이 경우 문자)가 있습니다 .1.02.0

현재 사용되는 명령은 다음과 같습니다.

sed -i 's/1\.0/2\.0/g' /home/user1/file1.txt

1.0and 가 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"

관련 정보