![sed를 사용하여 임의의 위치에 있는 문자를 바꾸시겠습니까?](https://linux55.com/image/70694/sed%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20%EC%9E%84%EC%9D%98%EC%9D%98%20%EC%9C%84%EC%B9%98%EC%97%90%20%EC%9E%88%EB%8A%94%20%EB%AC%B8%EC%9E%90%EB%A5%BC%20%EB%B0%94%EA%BE%B8%EC%8B%9C%EA%B2%A0%EC%8A%B5%EB%8B%88%EA%B9%8C%3F.png)
파일의 임의 위치에 있는 문자를 바꾸려고 합니다. 내 파일은 다음과 같습니다.
aab
babab
abab
"c"를 임의의 문자로 바꾸려고 합니다. 따라서 출력은 다음과 같습니다.
aab
bcbab
abab
모든 줄 바꿈을 제거하고 new_string.txt 파일에 저장한 다음 sed를 사용해 보았지만 작동하지 않습니다.
이것은 내가 시도한 코드입니다.
rand1="$(shuf -i 0-$tot_len -n 1)"
sed "s/^\(.\{"${rand1}"\}\)./\1G/" new_string.txt
계속 오류가 발생합니다.
sed: -e expression #1, char 25: Invalid content of \{\}
답변1
변수에는 중괄호가 필요하지 않으며 변수도 따옴표로 묶어야 합니다. 사용:
sed "s/^\(.\{$rand1\}\)./\1G/" new_string.txt
업데이트: 댓글에서 언급했듯이:
원래 코드는 괜찮지만 정수가 $rand1
너무 큽니다 sed
. 가능한 최대 값은 32767
GNU의 sed
이며 sed
여전히 16비트 정수만 필요하다는 것을 알았습니다.
다음을 통해 시스템 정규식 라이브러리의 한계를 얻을 수 있습니다(GNU는 sed
일반적으로 내장 버전을 사용하지만) .
$ getconf RE_DUP_MAX
32767
POSIX에서는 이 제한이 최소한 _POSIX_RE_DUP_MAX
(255)이어야 하며, 이는 이식성을 기대할 수 있는 최대값입니다(일부 시스템(예: Solaris 또는 OS/X)에는 이러한 낮은 제한이 있습니다).
답변2
GNU 시스템에서 문자(개행 제외)를 무작위로 바꾸려면 다음을 수행할 수 있습니다.
file=myfile.txt
offset=$(grep -bo . < "$file" | cut -d: -f1 | shuf -n1)
[ -z "$offset" ] || # file doesn't have non-newline characters
printf c | dd bs=1 seek="$offset" of="$file" conv=notrunc status=none
(이전 버전의 GNU dd
(8.20 이전) 의 경우 status=none
로 바꾸십시오 2> /dev/null
.)
grep -bo . < "$file"
파일의 개행 문자가 아닌 각 문자에 대한 바이트 오프셋을 제공합니다. 예를 들어 UTF-8로 인코딩된 파일에는 다음이 포함됩니다.
$3
£1
€2
이는 우리에게 다음을 제공합니다.
$ grep -bo . < "$file"
0:$
1:3
3:£
5:1
7:€
10:2
의 경우 cut -d: -f1
첫 번째 콜론 앞 부분을 유지합니다. 그런 다음 이러한 오프셋 중 하나를 무작위로 선택합니다 shuf -n1
.
이는 대체 문자가 대체되는 문자와 동일한 크기라고 가정합니다. 예를 들어 위의 £(2바이트)를 c(1바이트)로 바꾸면 파일 뒤에 c
잘못된 문자가 오게 됩니다.
이 문제를 해결하려면 데이터를 이동해야 하기 때문에 더 이상 파일을 제자리에 덮어쓸 수 없습니다.
다음과 같은 것이 필요합니다.
perl -C -0777 -pi -e "substr \$_, $offset, 1, 'c'" -- "$file"
대신에. 와 함께 -C
, perl
컴포지션의 로케일을 존중합니다.특징. -0777 -p
열려 있는흡연내용물을 $file
삼키는 모드 $_
(참조:perl -ne '...' 실행의 보안 위험 *이 건설의 안전 문제로 인해). 코드가 실행된 후 파일에 다시 쓰는 -pi
내부 편집 기능을 제공합니다 . 그런 다음 주어진 오프셋에서 1 문자 바꾸기를 $_
호출합니다 .substr
c
답변3
\n
새로운 GNU sed를 사용하면 ewline 제거 없이도 이 작업을 수행할 수 있습니다.
sed -z "s/./@/$(($RANDOM%$(wc -m < file.txt)))" file.txt
답변4
이 시도:
sed 's/^\(.\{'"${rand1}"'\}\)./\1G/' new_string.txt