다음 텍스트 파일이 있습니다.
#unimportant comment
#possible more unimportant comments
#info1 info2 info3 ,importantname1
importanttext1
#info1 info2 info3 ,importantname2
importanttext2
#info1 info2 info3 ,importantname3
importanttext3
각 파일을 별도의 파일로 나누고 싶습니다. 내가 정말로 필요한 것은 주석이 없는 URL을 추출하는 것입니다. 주석을 유지하는 것은 선택 사항입니다. 각 파일의 이름을 importantname1.txt로 지정하거나 각 주석 줄 끝에 쉼표를 추가하여 .txt로 지정하고 싶습니다.
따라서 importantname1.txt에는 다음 내용이 포함됩니다.
importanttext1
아니면 어쩌면
#info1 info2 info3 ,importantname1
importanttext1
따라서 행은 주석 처리된 파일 이름으로 추출 및 저장되며 이 경우 .txt 파일 이름 importantname1.txt가 추가됩니다.
이는 샘플 파일의 각 행 세트에 대해 수행되어야 합니다. 주석을 유지하는 것은 중요하지 않지만 스크립트 작성이 가능해야 합니다. 또한 헤더에 있는 알 수 없는 수의 주석 줄도 고려해야 합니다. 주석 줄은 항상 각 importanttextX 줄 앞에 옵니다.
답변1
노력하다:
awk -F, '/^#/{f=$NF".txt";cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file
예
예제 입력에 적용됩니다.
$ awk -F, '/^#/{f=$NF".txt";cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file
위를 실행하면 디렉토리에 다음과 같은 파일이 있습니다.
$ ls
file importantname1.txt importantname2.txt importantname3.txt
새 파일의 내용은 다음과 같습니다.
$ cat importantname1.txt
#info1 info2 info3 ,importantname1
importanttext1
$ cat importantname2.txt
#info1 info2 info3 ,importantname2
importanttext2
$ cat importantname3.txt
#info1 info2 info3 ,importantname3
importanttext3
어떻게 작동하나요?
awk는 입력 파일을 한 줄씩 읽습니다. 우리 스크립트는 이러한 줄을 주석 또는 비주석으로 분류합니다. 주석 라인의 경우 파일 이름과 주석이 저장됩니다. 댓글이 없는 경우 새 파일이 생성되어 인쇄됩니다.
`-F,
이는 awk에게 입력 필드 구분 기호로 쉼표를 사용하도록 지시합니다. 이렇게 하면 파일 이름이 항상 마지막 필드가 됩니다.
/^#/{f=$NF".txt";cmt=$0; next}
줄이 로 시작하는 경우 파일 이름 과
#
마지막 필드 로 저장합니다 . 주석이 달린 전체 줄은 로 저장됩니다 . 그런 다음 awk에게 명령의 나머지 부분을 건너뛰고 해당 줄로 이동하여 다시 시작하도록 지시합니다.$NF
.txt
f
cmt
next
printf "%s\n%s\n",cmt,$0 >f; close(f)
주석이 아닌 줄의 경우 마지막으로 본 주석
cmt
과 현재 줄을$0
마지막으로 본 filename 에 인쇄합니다f
. 그런 다음 파일 핸들을 닫습니다f
.
잘못된 파일 이름 방지
파일 이름으로 사용하려는 필드가 포함된 경우 /
운영 체제는 파일 이름에 디렉터리가 포함된 것으로 해석합니다. 이를 방지하려면 다음과 같이 모두를 using /
으로 바꿀 수 있습니다.-
gsub(/\//, "-", f)
awk -F, '/^#/{f=$NF".txt";gsub(/\//, "-", f); cmt=$0; next} {printf "%s\n%s\n",cmt,$0 >f; close(f)}' file
답변2
grep
A와 B의 조합은 a) 주석 처리되지 않은 모든 행과 이전 메시지 1을 핑하고 b) 메시지 주석 행을 기준으로 출력을 분할하여 csplit
작업을 수행할 수 있습니다 .grep
grep -v -B1 '^#' file | csplit -z - '/^#/' '{*}'
즉, -v
시작 부분에 #이 있는 줄을 추출 하지 말고 ^#
, 이 줄 앞의 줄을 추출하십시오 -B1
. 그런 다음 -
줄 시작 부분의 #마다 들어오는 파이프 입력을 분할하고, 빈 파일을 무시 -z
하고 가능한 한 자주 이 작업을 수행합니다 {*}
.
이름 바꾸기는 별도의 단계여야 합니다( csplit
출력 이름을 xx00, xx01...로 자동 지정 - 접두사와 접미사를 각각 변경하려면 -f
및 옵션을 사용하세요).-b
#/bin/bash
for f in xx* ; do
mv "$f" "$( sed -n '2p' "$f" )".txt
done