다음 텍스트 파일이 있습니다.
#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
따라서 행이 추출되어 주석 뒤에 파일 이름으로 저장되고 이 경우 파일 이름 importantname1.txt에 .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}
줄이 로 시작하면
#
마지막 필드인$NF
와.txt
파일 이름을 저장합니다f
. 주석 줄 전체가cmt
. 그런 다음 awk에게 나머지 명령을 건너뛰고 점프하여 해당next
줄에서 다시 시작하도록 지시합니다.printf "%s\n%s\n",cmt,$0 >f; close(f)
주석이 아닌 줄의 경우 마지막으로 본 주석
cmt
과 현재 줄을$0
마지막으로 본 파일 이름에 인쇄합니다f
. 그런 다음 에 대한 파일 핸들을 닫습니다f
.
잘못된 파일 이름으로부터 보호
파일 이름으로 사용될 필드에 가 포함되어 있으면 /
OS는 파일 이름을 디렉터리를 포함하는 것으로 해석합니다. 이를 방지하기 위해 다음과 같이 모두를 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
a) 칭찬되지 않은 모든 줄과 앞의 정보 줄을 핑하고 b) 정보 주석 줄을 기준으로 출력을 분할하여 grep
작업 을 수행할 수 있습니다.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