sed는 while 루프의 변수를 대체하지 않습니다.

sed는 while 루프의 변수를 대체하지 않습니다.

sed에서 변수의 줄번호를 사용하려고 하면 단독으로 작동하는데, while 루프를 사용하여 같은 작업을 하면 작동하지 않습니다.

예를 들어.

cat file
den 
run
ten
run
fan

linenumber=2
replacetext=34
sed -i ""$linenumber"s/run/run\n"$replacetext"/" file

Output:
cat file
den
run
34
ten
run
fan

위의 작업은 변수 확장 후에 sed 명령이 생성됩니다.

그러나 while 루프에서 동일한 방법을 사용하면 순수한 sed 솔루션을 사용하여 모든 인스턴스를 증가하는 줄 번호로 바꾸고 싶기 때문에 첫 번째 인스턴스에서만 작동하고 모든 인스턴스에서는 작동하지 않습니다. awk 또는 Perl 솔루션이 필요하지 않습니다.

예를 들어.

replacetext=1
while read in; do replacetext=$((replacetext++)) && sed ""$in"s/run/run\n"$replacetext"/" file; done <<< "$(cat file | grep 'run' -n | cut -f1 -d ':')"

예상 출력: 일치하는 텍스트가 자체적으로 바뀌고 그 뒤에 개행 문자와 증분 숫자가 옵니다.

den 
run
2
ten
run
3
fan

얻은 출력:

den
run
2
ten
run
fan

sed 기반 솔루션만 필요합니다. while 루프에서 어떤 이상한 동작이 일어나고 있는지 궁금합니다. 작동하지 않습니다. 루프 변수에 줄 번호 값이 할당되기 때문에 해당 줄 번호는 sed에서 해당 줄의 Macthed 텍스트를 대체하는 데 사용되며 그 뒤에 개행 문자와 증분 숫자가 옵니다.

Sed는 동일한 변수 줄 번호를 제공할 때 작동하는 것처럼 보이지만 while 루프에서는 작동하지 않습니다.

답변1

<<< 뒤에 오는 내용이 올바른 줄 번호 목록을 가져오기 때문에 실패합니다.원본 파일에.

그런 다음 파일을 여러 번 편집하고추가 행 삽입.

그래서 첫 번째 것을 제외한 모든 sed는 다음과 같이 전달됩니다.잘못된 줄 번호s/// 명령의 경우.

한 가지 해결 방법은 줄 번호 목록을 반대로 바꾸는 것입니다. 이렇게 하면 편집 내용이 이전 번호에 영향을 주지 않습니다.

이것은 파이프에 있는 sed 솔루션인데 약간 이상합니다.

첫 번째 sed는 = 연산자를 사용하여 패턴이 발견된 줄 번호를 가져옵니다. nl은 각 줄 앞에 일련 번호를 추가합니다.3 10

두 번째 sed는 sed 표현식을 출력합니다. 이는 각 행을 원하는 sed 편집으로 변환합니다(예: ) 10 s/$/\n3/.

세 번째 sed는 stdin에서 이러한 편집 내용을 수집 및 적용하고 파일을 제자리에서 편집합니다. 이 경우 자체적으로 편집됩니다.

스크립트 자체는 다음과 같습니다.

#! /bin/bash

Pattern="[Ss]ed"

RegEx='[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*'
DoSed='\2 s/\$/\\n\1/'

sed -n -e "/${Pattern}/=" badSed |
    nl -ba |
    sed -e "s:${RegEx}:${DoSed}:" |
    sed -i -f - badSed
 

이것이 그 자신에게 하는 일입니다:

#! /bin/bash

Pattern="[Ss]ed"

RegEx='[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*'
DoSed='\2 s/\$/\\n\1/'
1

sed -n -e "/${Pattern}/=" badSed |
2
    nl -ba |
    sed -e "s:${RegEx}:${DoSed}:" |
3
    sed -i -f - badSed
4

답변2

대체가 필요한 줄 번호가 엉망입니다.

따라서 우리는 while 루프가 먼저 유효한 sed 명령 세트를 생성한 다음 이를 입력 파일에 다시 적용하도록 허용하는 대체 전략을 고안했습니다.

replacetext=1
while read in; do ((replacetext++)); echo "$in s/\$/\\n$replacetext/"; done <<<"$(grep -n run file | cut -d: -f1)" | sed -f - file > tmp && mv tmp file 

관련 정보