나는 마법이 절실히 필요하다는 것을 깨달았습니다 sed
.진짜나는 앉아서 이것을 배워야 한다). 줄이 많은 파일이 있습니다. 검토한 후 줄 시작 부분에 별표(*)를 추가하여 일부 줄을 표시했습니다.
(가능하다면) 내가 하고 싶은 몇 가지 트릭은 sed
모든 마커 라인을 파일의 시작 부분(또는 끝 - 까다롭지 않음)으로 이동하여 블록을 형성하는 것입니다. 표시되지 않은 다른 선은 방해받지 않아야 합니다.
어떻게 이런 일을 할 수 있나요 sed
? sed
텍스트 이동을 위한 버퍼가 있다는 것을 알고 있습니다 .
답변1
sed가 필요한가요? 소스 파일을 두 번 살펴보는 것이 괜찮다면 grep을 사용하여 쉽게 수행할 수 있습니다.
예를 들어
grep '^\*' input > outputfile
grep -v '^\*' input >> outputfile
답변2
파일 크기에 따라 다음을 수행할 수 있습니다.
sed '/^*/!H;//p;$!d;g;s/\n//'
H
일치하지 않는 오래된 공간 라인 에 쌓여 있습니다 /^*/
. 해당 일치 항목은 p
입력에 나타나는 대로 인쇄됩니다. 그런 다음 !
마지막 행이 아닌 모든 행이 출력에서 제거됩니다 $
. d
마지막 줄에서는 g
패턴 공간을 덮어써서 공간을 보존한 다음, 첫 번째 줄이 매번 추가 문자를 생성하므로 첫 번째 \n
ewline 문자가 대체됩니다 .s/\n//
H
H
그러나 이는 이미 모든 행을 이전 공간 에 저장하고 있기 때문에 큰 버퍼가 필요합니다 . 한편, 이...
sed '/^*/p;$!d;g;r file' <file |
sed -e '1,/^$/{/./p;d' -e '};/^*/d'
...그런 요구 사항은 없습니다.
첫 번째는 마지막 줄 까지 일치하는 줄만 sed
p
인쇄하고 , 마지막 줄에서는 빈 줄을 인쇄한 다음 전체 입력 파일을 다시 읽습니다./^*/
$
r
두 번째는 sed
먼저 첫 번째 줄부터 첫 번째 빈 줄까지의 줄 범위 내에서 작동하여 p
최소한 단일 문자와 일치하는 모든 줄을 인쇄한 다음 d
일괄 처리를 삭제합니다. 첫 번째 빈 줄을 만난 후 d
일치하는 모든 줄을 삭제합니다 /^*/
.
답변3
이 작업을 수행할 필요는 없으며 sed
기본 grep을 사용하여 별표(*) 줄을 맨 위로 끌어올 수 있습니다. 다음 파일이 있다고 가정해 보겠습니다.
$ cat sample.txt
1
2
3
4
* 5
* 6
* 7
8
9
10
이제 grep
이전 example.txt 파일에 별표(*) 줄을 추가합니다.
$ cat <(grep '*' sample.txt) <(grep -v '*' sample.txt)
* 5
* 6
* 7
1
2
3
4
8
9
10
위의 명령은 2개의 grep을 실행합니다. 첫 번째 명령은 별표가 있는 모든 줄을 꺼내고, 두 번째 명령은 별표가 아닌 모든 줄을 가져옵니다. 이 두 명령의 출력은 명령에 대한 입력으로 기호 리디렉션을 cat
사용합니다 .<()
대체 방법
cat + 2 하위 쉘을 사용하지 않으려면 @terdon이 제안한 대로 수행할 수 있습니다.
$ grep '*' sample.txt; grep -v '*' sample.txt
sample.txt
그러면 별표(*)가 포함된 모든 줄이 추출되고 , 그 뒤에는 별표(*)가 포함되지 않은 모든 줄이 표시됩니다.
인용하다
답변4
두 블록 사이에 빈 줄이 있어도 괜찮다면:
sed -n -e '/^* /{H;$!d}' -e '/^* /!p' -e '${g;p}'
혹은 그 반대로도
sed -n -e '/^* /{p;$!d}' -e '/^* /!H' -e '${g;p}' file