라인에서 매개변수와 값을 캡처하는 방법

라인에서 매개변수와 값을 캡처하는 방법

segment.bytes우리는 매개변수 와 해당 값을 캡처하고 싶습니다.

echo "$info" | grep "segment.bytes"
{"version":1,"config":{"segment.bytes":"10737555","retention.bytes":"104857600"}}

내 생각은 값을 포함하지만 값을 포함하지 않는 모든 단어를 제거 segment.bytes하고 제거하는 것입니다.segment.bytes큰따옴표

예상 결과의 예

echo "$info" | grep "segment.bytes" |  ......

segment.bytes:10737555

나는 이것을 시도 할 것이다

echo "$info" | grep "segment.bytes"   | sed s'/"/ /g' |  sed 's/^.*segment.bytes/segment.bytes/' | awk '{print $1":"$3}

나는 얻다

segment.bytes:10737555

하지만 가치를 얻는 결과가 매우 높기 때문에 내 접근 방식이 위험할 수 있다고 생각합니다.예민한중요한 것은 잘못된 결과를 얻을 수도 있다는 것입니다.비참한

더 신뢰할 수 있는 다른 옵션이 있으면 좋겠습니다.

답변1

$info다음 호출을 통해 sed변수를 파이프 할 수 있습니다 .

echo "$info" | sed -E '/"segment\.bytes"/s/.*"(segment\.bytes)":"([^"]+)".*/\1:\2/'

패턴이 있는 행을 찾고 문자열 "segment.bytes"segment.bytes대괄호 안의 다음 문자열( "단순화를 위해 "그러나"로 정의됨)을 캡처 그룹 1과 2로 추출하고 "캡처 그룹 1", ":" 및 "캡처 그룹"을 인쇄합니다. 2".

(확장 정규식을 활성화하는 옵션은 sed버전에 따라 다를 수 있습니다. -E이제 POSIX 표준이며 현재 GNU, MacOS 및 BSD에서 작동 sed하지만 실패할 경우 ERE 페이지 활성화 방법에 대한 매뉴얼을 확인하세요.)

좀 더 선택적으로 시도해 보세요.

sed -E '/"segment\.bytes":"[0-9]+"/s/.*"(segment\.bytes)":"([0-9]+)".*/\1:\2/'

행 검색 및 값 캡처 부분에서는 정수 값만 허용합니다.

답변2

grep전화하기 전에 전화할 필요가 없습니다 sed.

$ echo "$info"
foo
{"version":1,"config":{"segment.bytes":"10737555","retention.bytes":"104857600"}}
bar

$ echo "$info" | sed -n 's/.*"\(segment\.bytes\)":"\([^"]*\)".*/\1:\2/p'
segment.bytes:10737555

또는 전체 행에 대한 매우 구체적인 일치의 경우 잘못된 일치 가능성이 거의 불가능하지만 분명히 입력 형식의 변경에 더 민감합니다.

$ echo "$info" |
sed -n 's/^{"version":[0-9][0-9]*,"config":{"\(segment\.bytes\)":"\([0-9][0-9]*\)","retention\.bytes":"[0-9][0-9]*"}}$/\1:\2/p'
segment.bytes:10737555

위의 내용은 모든 sed에 적용됩니다.

답변3

안전하고 신뢰할 수 있는 방법은 jq유틸리티를 사용하는 것입니다.

$ echo "$info" \
| grep -F  '"segment.bytes"' \
| jq  -r '.config | "segment.bytes:" +  ."segment.bytes"' 

큰 타격:

parameter substitutions왼쪽과 오른쪽 끝에서 잘라내고 세그먼트.바이트 속성 값을 추출합니다.

name="segment.bytes"
var=${info#*\"${name}\":\"}
printf "%s:%s\n" "$name"  "${var%%\"*}"'

또 다른 방법은 먼저 tye 정보 문자열을 중괄호의 쉼표와 줄 바꿈으로 분할하여 grep이 해당 작업을 수행하고 grep의 출력에서 ​​큰따옴표를 제거할 수 있도록 하는 것입니다.

$ echo "$info" \
| tr '{,}' '[\n*]' \
| grep '^"segment\.bytes"' \
| tr -d \"

JSON 모듈과 함께 Perl 사용

$ echo "$line" | grep -F  '"segment.bytes"' \
| perl -MJSON -lne '$,=":";
  my $k = "segment.bytes";
  print $k, decode_json($_)->{config}{$k};
'

JSON 모듈을 사용할 수 없는 경우에도 이 작업을 수행할 수 있습니다. 여기서는 먼저 sed를 사용하여 유효한 Perl 코드를 생성한 다음 do 문을 통해 Perl에서 이를 구현합니다. 그러면 json 객체 $j는 우리가 원하는 키를 추출할 수 있는 해시 참조입니다.

$ echo "$info" \
| sed  \
    -e '/"segmen\.bytes"/!d'  \
    -e 'y/:/,/;s/.*/$j=&;/' \
  > ./foo.json 
$ perl -I. -le '$,=":";
  my $name = "segment.bytes";
  do "foo.json" or die $!;
  print $name, $j->{config}{$name};
'

awk와 sed는 설명이 필요 없습니다.

$ echo "$info" | grep -F segment.bytes \
| awk -F '"segment\\.bytes":"'  '
  {
    t = $2
    sub(/".*/, "", t)
    $0 = FS t
    gsub(/["\\]/, "")
  }1'
$ echo "$info" | grep -F segment.bytes \
| sed -ne '
    y/{,}/\n\n\n/
    /^"segment.bytes"/!D
    s/"//g;P
  ' 

답변4

다음 awk 명령을 사용할 수 있습니다

echo "$info"|awk -F "," '/segment.bytes/{for(i=1;i<=NF;i++){if($i ~ /segment/){gsub("\"","",$i);print $i }}}'| sed "s/.*{//g"

산출

segment.bytes:10737555

관련 정보