특정 카테고리 제목부터 다음 카테고리 제목까지 텍스트 파일에서 텍스트를 추출합니다.

특정 카테고리 제목부터 다음 카테고리 제목까지 텍스트 파일에서 텍스트를 추출합니다.

다음 형식의 TOML 파일이 있습니다(범주에는 어떤 이름이든 가질 수 있으며 일련 번호 매기기는 단지 예일 뿐이며 보장되지는 않습니다).

[CATEGORY_1]
A=1
B=2

[CATEGORY_2]
C=3
D=4

E=5

...

[CATEGORY_N]
Z=26

내가 달성하고 싶은 것은 주어진 카테고리 내에서 텍스트를 검색하는 것입니다.

따라서 내가 지정하면 [CATEGORY_1]출력이 제공되기를 원합니다.

A=1
B=2

나는 플래그를 사용하여 개행 문자를 널 바이트 문자로 해석하고 다음 정규식을 사용하여 grep이를 수행하려고 했습니다 .z

(^\[.*])             # Match the category 
  ((.*\n*)+?         # Match the category content in a non-greedy way
    (?=\[|$))        # Lookahead to the start of other category or end of line

^처음에 표현식을 제거하지 않으면 작동하지 않습니다. 그러나 이렇게 하면 느슨한 괄호 쌍을 카테고리로 잘못 해석하게 됩니다.

이 작업을 올바르게 수행할 수 있는 방법이 있나요? 그렇지 않은 경우 또는 grep같은 다른 도구를 사용하십시오 .sedawk

답변1

tomlqTOML jq래퍼 사용을 고려할 수 있습니다.yq 프로젝트name, 간단히 구문을 사용하여 jq카테고리의 내용을 검색할 수 있습니다..name

전임자. 주어진:

$ cat file.toml 
[CATEGORY_1]
A=1
B=2

[CATEGORY_2]
C=3
D=4

E=5


[CATEGORY_N]
Z=26

그 다음에

$ tomlq -t '.CATEGORY_1' file.toml
A = 1
B = 2

...명령줄에 제공된 부분 이름을 사용합니다.

$ tomlq -t --arg section 'CATEGORY_1' '.[$section]' file.toml
A = 1
B = 2

출력은 TOML 형식입니다. 탭으로 구분된 출력을 원하십니까?

$ tomlq -r --arg section 'CATEGORY_1' '.[$section] | to_entries[] | [ .key, .value ] | @tsv' file.toml
A       1
B       2

@csv대신 CSV 출력을 얻으려면 사용하세요 @tsv.


원래 grep 솔루션을 요청했으므로 다음과 같습니다 pcregrep.

$ pcregrep -Mo '(?s)\[CATEGORY_1\]\n\K.*?(?=\n+\[)' file.toml
A=1
B=2

여기서는 여러 행을 일치시키는 데 (?s)사용됩니다 . 너.\n.*?할 수 있는-z다음 플래그를 사용하여 PCRE 모드에서 GNU grep을 사용하여 가짜로 만듭니다.

$ grep -Pzo '(?s)\[CATEGORY_1\]\n\K.*?\n(?=\n+\[)' file.toml
A=1                                                                                                                                                                                          
B=2

길이가 고정되어 있으므로 대칭을 선호하는 경우 정면도와 일치하도록 \[CATEGORY_1\]\n\K후면도로 교체 할 수 있습니다.(?<=\[CATEGORY_1\]\n)(?=\n+\[)

답변2

pure 보다 약간 더 복잡 sed하지만 더 많은 미세 조정이 가능합니다.

$ awk -v catname="[CATEGORY_1]" '/^\[.*\]$/{p=($0==catname)} p' input.toml
[CATEGORY_1]
A=1
B=2

  • 명령줄에서 원하는 범주 이름을 awk변수 로 지정할 수 있습니다 catname.
  • 프로그램 내에서 플래그가 p1로 설정되면 현재 줄을 인쇄합니다(참조:여기작동 방식에 대해).
  • "범주 시작 패턴"(줄이 로 시작 [하고 끝남 ])을 발견하면 플래그를 0으로 설정하지만 줄이 범주 이름과 정확히 일치하면 플래그를 1로 설정합니다(어떤 의미에서는 The를 설정합니다). 현재 줄이 )에 저장된 문자열과 같은지 p확인한 결과입니다 .$0catname

이렇게 하면 카테고리 제목의 시작부터 다음 카테고리 제목까지 모든 내용이 인쇄됩니다.

목표 확장

카테고리 제목을 생략하고 싶다면 변경할 수 있습니다.

{p=($0==catname)}

도착하다

{p=($0==catname); next}

그러면 조건부 인쇄 명령을 우회하여 플래그가 설정되자마자 다음 줄로 점프합니다.

또한 빈 줄을 제외하려면 p프로그램 끝에 있는 "외견상 길을 잃은 것처럼 보이는"을 로 변경하십시오 p&&NF. 이는 플래그가 p0이 아니고 하나 이상의 "필드"(예: 0이 아닌 경우) 에만 올바른 텍스트입니다. 공백) )을 현재 행에 입력합니다.

답변3

내가 올바르게 이해했다면 다음 명령을 사용할 수 있습니다 sed.

# Choose the category until the next [ character
# and then delete any line starting with the [ character
$ sed -n '/^\[CATEGORY_2\]/,/^\[/p' file | sed '/^\[/d'
C=3
D=4

E=5

관련 정보