텍스트 파일을 고려하십시오 users.txt
.
#alice
#bob
charlie
dotan
eric
마지막 주석 처리된 줄(제외)부터 (포함)까지 모든 내용을 주석 처리해야 합니다 dotan
. 결과는 다음과 같습니다.
#alice
#bob
#charlie
#dotan
eric
sed
이를 수행할 수 있는 좋은 oneliner가 있습니까 ?나는 단지 , 정말로 어떤 도구라도 만족할 것입니다 sed
.
현재 다음과 같이 마지막 주석이 달린 줄의 줄 번호가 표시됩니다.
$ cat -n users.txt | grep '#' | tail -n1
2 #bob
그런 다음 하나를 추가하고 댓글을 남깁니다 sed
.
$ sed -i'' '3,/dotan/ s/^/#/' users.txt
나는 똑똑할 수 있고 모든 것을 무언가와 결합하여 bc
추악한 농담으로 만들 수 있다는 것을 알았습니다.확실히 더 깨끗한 방법이 있어야합니까?
답변1
기존 주석 줄이 연속 블록을 형성하는 경우 다음으로 시작할 수 있습니다.첫 번째대신, 아직 주석 처리되지 않은 종료 패턴까지만 주석 처리하여 행을 주석 처리하십시오.
sed '/^#/,/dotan/ s/^[^#]/#&/' file
기존 주석이 연속되지 않으면 sed의 범위 일치의 탐욕스러운 특성으로 인해 이와 같은 작업을 수행해야 할 것 같습니다.
tac file | sed '/dotan/,/^#/ s/^[^#]/#&/' | tac
즉 일치위로종료 모드에서 "첫 번째" 주석까지 - 내부 솔루션을 원하는 경우 이는 분명히 그리 편리하지 않습니다.
답변2
어때요?
perl -pe '$n=1 if s/^dotan/#$&/; s/^[^#]/#$&/ unless $n==1;' file
또는 awk에서도 동일한 아이디어가 적용됩니다.
awk '(/^dotan/){a=1; sub(/^/,"#",$1)} (a!=1 && $1!~/^#/){sub(/^/,"#",$1);}1; ' file
답변3
단일 호출로 두 가지 경우(단일 연속 블록의 주석 처리된 줄 또는 주석 처리되지 않은 줄 사이에 배치된 줄)를 모두 처리할 수 있습니다 sed
.
sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile
이는 범위 내의 행만 처리합니다 1,/PATTERN/
. x
보유 공간 w를 변경합니다 . 패턴 공간은 행에 주석이 달릴 때마다 사용되며(따라서 보존 버퍼에 주석이 달린 행은 두 개 이상 있을 수 없음) 주석 처리되지 않은 각 행은 H
이전 공간에 추가됩니다(첫 번째 행에 있을 때 1d
각각 1h
제거가 필요함). 버퍼에 빈 라인을 유지하기 위해 초기 라인의 ).
PATTERN과 일치하는 라인에 도달하면 이를 H
기존 버퍼 에 추가하고 x
버퍼를 변경한 다음 \n
패턴 공간의 모든 ewline 문자를 ewline 및 ewline으로 바꿉니다(즉, 패턴 공간의 모든 라인 이제 모두 첫 번째 줄을 예약된 공간으로 포함합니다(첫 번째 줄은 항상 주석 줄입니다). 샘플이 있습니다:\n
#
#
infile
alice
#bob
bill
#charlie
ding
dong
dotan
jimmy
#garry
달리기:
sed '1,/dotan/{ # if line is in this range -start c1
/^#/{ # if line is commented -start c2
x # exchage hold space w. pattern space
1d # if 1st line, delete pattern space
b # branch to end of script
} # -end c2
//!{ # if line is not commented -start c3
H # append to hold space
/dotan/!{ # if line doesn't match dotan -start c4
1h # if 1st line, overwrite hold space
d # delete pattern space
} # -end c4
//{ # if line matches dotan -start c5
x # exchage hold space w. pattern space
s/\n/&#/g # add # after each newline character
} # -end c5
} # -end c3
}' infile # -end c1
산출:
alice
#bob
bill
#charlie
#ding
#dong
#dotan
jimmy
#garry
따라서 다른 줄은 변경하지 않고 에서 (및 제외) #charlie
부터(및 포함)까지 의 줄만 주석 처리합니다 . 물론, 이는 일치하는 line 앞에 항상 최소한 하나의 주석 행이 있다고 가정합니다 . 그렇지 않은 경우 교체하기 전에 추가 검사를 추가할 수 있습니다.dotan
PATTERN
/^#/{s/\n/&#/g}
답변4
여기 또 다른 것이 있습니다 sed
:
sed -e:n -e'/\n#.*\ndotan/!{$!{N;/^#/bn' \
-eb -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et -e\} -eP\;D <in >out
이것이 바로 당신이 요청한 것입니다. 이는 스택에서만 작동합니다. 필요할 때 주석 줄이 나타나는 사이에 필요한 시간 동안 빌드하고 주석 줄이 발견되면 입력에서 새 주석 줄을 지원하기 위해 이전 버퍼를 덤프합니다. 그림...
죄송합니다. 제가 왜 이런 짓을 했는지 모르겠습니다. 그러나 나는 그것에 대해 생각했습니다.
시리즈의 마지막 주석 처리된 각 줄 사이에 버퍼를 어떻게 sed
배포하더라도 마지막 주석 처리된 이벤트를 정확하게 추적하는 데 필요한 것보다 더 많은 것을 버퍼에 유지하지 않으며 언제든지 마지막 줄을 만나면 다음을 시도합니다. 최종 g
로컬 실행 문과 분기를 사용 t
하여 전체 버퍼를 인쇄합니다. 그렇지 않으면 P
버퍼에서 해제된 모든 줄을 즉시 인쇄합니다.
아무래도 아코디언이 생각나는 것 같아요...
printf %s\\n \#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric |
sed -e:n -e'l;/\n#.*\ndotan/!{$!{N;/^#/bn' \
-eb -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et -e\} -eP\;D
#alice
#alice\n#bob$
#alice\n#bob\ncharlie$
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob
#charlie
#dotan
eric
이 명령과 위 명령의 차이점은 딱 하나인데, l
상단에 있는 ook 명령입니다. 패턴 공간이 어떻게 작동하는지 l
관찰 하면 sed
뒤에서 무슨 일이 일어나고 있는지 더 잘 이해하고 작업을 지시하는 방법을 더 잘 이해할 수 있습니다.
이 경우 두 번째 입력 항목을 찾을 때까지 그리고 이전 입력을 한 번에 한 줄씩 인쇄하기 시작할 때까지 sed
입력 스택을 볼 수 있습니다. \n#.*\ndotan
정말 멋지네요. 나는 이 분야에서 많은 것을 배웠다.