다음 형식의 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
같은 다른 도구를 사용하십시오 .sed
awk
답변1
tomlq
TOML 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
. - 프로그램 내에서 플래그가
p
1로 설정되면 현재 줄을 인쇄합니다(참조:여기작동 방식에 대해). - "범주 시작 패턴"(줄이 로 시작
[
하고 끝남]
)을 발견하면 플래그를 0으로 설정하지만 줄이 범주 이름과 정확히 일치하면 플래그를 1로 설정합니다(어떤 의미에서는 The를 설정합니다). 현재 줄이 )에 저장된 문자열과 같은지p
확인한 결과입니다 .$0
catname
이렇게 하면 카테고리 제목의 시작부터 다음 카테고리 제목까지 모든 내용이 인쇄됩니다.
목표 확장
카테고리 제목을 생략하고 싶다면 변경할 수 있습니다.
{p=($0==catname)}
도착하다
{p=($0==catname); next}
그러면 조건부 인쇄 명령을 우회하여 플래그가 설정되자마자 다음 줄로 점프합니다.
또한 빈 줄을 제외하려면 p
프로그램 끝에 있는 "외견상 길을 잃은 것처럼 보이는"을 로 변경하십시오 p&&NF
. 이는 플래그가 p
0이 아니고 하나 이상의 "필드"(예: 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