Linux bash에서 정규식을 사용하여 json 값 가져오기

Linux bash에서 정규식을 사용하여 json 값 가져오기

JSON 파일이 있습니다파일.json이와 같이:

{
  "abc": "123",
  "def": 456,
  "ghi": 789
}

bash 터미널에서 정규식을 사용하여 모든 키의 값을 얻으려고 합니다.

이것이 내가 가치를 얻으려고 노력하는 방법입니다.알파벳:

var=cat file.json
regex='(abc\":) \"(.+)\",'
[[ $var =~ $regex ]]
echo ${BASE_REMATCH[1]}

아무것도 인쇄하지 않습니다. 값을 가져오거나 인쇄하려고 합니다.알파벳"123"

jq가 필요한 컴퓨터에서 사용할 수 없고 설치할 수도 없기 때문에 jq를 사용할 수 없습니다.

답변1

다음과 같은 것이 필요합니다.

var=$(cat file.json) || exit
regex='"abc"[[:space:]]*:[[:space:]]*"((\\.|[^"\\])*)"'
if [[ $var =~ $regex ]]; then
  value=${BASH_REMATCH[1]}
  printf '%s\n' "$value"
fi

하지만 그런 경우에도 실제 값을 얻으려면 json 문자열을 디코딩해야 합니다. 예를 들어 합계 foo\"\nbar로 변환해야 합니다 foo"<newline>bar.\u0031\u0032\u0033123

적합한 json 파서를 사용하는 것이 더 좋습니다.

value=$(jq .abc < file.json)
value=$(PERL_UNICODE= json_xs -t none -e 'print $_->{abc}' < file.json)
value=$(perl -C -MJSON -0777 -ne 'print decode_json($_)->{abc}' file.json)
value=$(
  python3 -c 'import sys, json; print(json.load(sys.stdin)["abc"])' < file.json
)

접근 방식의 문제점은 다음과 같습니다.

  • 명령의 출력을 가져오는 구문은 더 이상 $(cmd)사용되지 않습니다 `cmd`. var=cat file.json해당 환경에 전달된 명령을 실행하려고 합니다 file.json.var=cat
  • \"정규식에서는 의미가 없습니다. 동일한 것으로 간주될 수 있지만 "보장할 수는 없습니다.
  • .+가능한 한 많은 문자와 일치하므로 문자열의 "마지막 문자 까지 s 및 개행 문자와 일치합니다. 여기서는 "0개 이상의 (not) 뒤에 or를 제외한 단일 문자가 오는 시퀀스 로 대체하므로 이스케이프되지 않은 다음 문자로 실행됩니다.*+\\""
  • 정규식에 두 개의 캡처 그룹이 있고 첫 번째 캡처 그룹이 일치하며 (abc\":)분명히 두 번째 캡처 그룹(값)이 필요합니다.
  • 변수는 $BASH_REMATCH, 는 아닙니다$BASE_REMATCH
  • 임의의 데이터를 출력하는 데 사용할 수 없습니다 echo.
  • 적어도 목록의 맥락에서는 bash에서 매개변수 확장을 인용해야 합니다.

답변2

파일이 표시된 것처럼 정말 간단한 경우(문자열 값에 특수 JSON 인코딩이 없음) 다음을 사용합니다 awk.

$ awk '$1=="\"abc\":"{print $2}' file | tr -d '",'
123

심지어 GNU grep:

$ grep -oP '"abc":\s*"?\K[^,]+' file | tr -d '",'
123

PCRE 정규 표현식을 활성화 하고 "지금까지 일치하는 모든 것을 무시" -P합시다 . 옵션 ("줄에서 일치하는 부분만 인쇄")을 \K사용하면 올바른 일치 항목을 찾은 다음 이를 폐기하여 출력에 포함되지 않도록 할 수 있습니다. 따라서 여기서는 0개 이상의 공백 문자( ), 0 또는 따옴표( )가 뒤 따르는 문자열을 찾고 지금까지의 모든 항목을 삭제한 다음 문자가 아닌 가장 긴 문자( ) 를 찾습니다 .\K-o"abc":\s*"?"[^"]+

마지막으로 또는 문자가 tr제거되고 값은 따옴표 없이 그대로 유지됩니다.",

관련 정보