긴 파일에서 텍스트 줄 추출

긴 파일에서 텍스트 줄 추출

다음 텍스트 파일이 있습니다.

#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.txtfcmtnext

  • 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

grepA와 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

관련 정보