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\u0033
123
적합한 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
제거되고 값은 따옴표 없이 그대로 유지됩니다."
,