
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