sed는 파이프를 통해 마지막 문자 인스턴스를 제거합니까?

sed는 파이프를 통해 마지막 문자 인스턴스를 제거합니까?

여러 줄 변수에 생성된 json 배열이 있지만 [{"name":"a"},{"name":"b"},{"name":"c"},]형식, 줄 바꿈 또는 공백에 관계없이 에서와 같은 마지막 쉼표를 제거해야 합니다.

나는의 답변을 사용하려고합니다이 Q&A하지만 파일 대신 변수를 입력으로 사용하고 있습니다.

예를 들어 sed 버전은 다음과 같습니다.

echo "$json" | sed -n 'x;${s/,$//;p;x}; 2,$ p'

나는 예제와 동일하게 시도하고 있지만 awk성공하지 못했습니다.

파이프를 사용하여 얻을 수 있는 유일한 대답은 Perl 페이지 아래에 있습니다 echo "$json" | perl -0777 -pi -e 's/(.*),(.*?)/\1\2/s'.

sed나는 대신에 perl다음을 사용하고 싶습니다 .지역 설정for는 perl내가 관리하는 컴퓨터에 항상 설정되어 있는 것은 아닙니다.

파이프 작업을 위해 sed 명령을 어떻게 수정합니까?

답변1

귀하가 취한 (훌륭한 btw) 답변은 두 번째 줄의 변경 사항에만 적용됩니다.

한 줄만 있으면 @I_GNU_it_all_along이 다음 ,]과 같이 바꾸는 것이 훨씬 쉽습니다 ].

echo "$json" | sed 's/,]/]/'

또는 GNU의 일반 솔루션을 사용하여 파일의 마지막 문자 인스턴스를 제거하십시오 sed.

echo "$json" | sed -z 's/\(.*\),/\1/'

그것은 무엇을 합니까? 이 -z옵션은 sed한 줄씩 처리하지 않고 전체 버퍼를 한 번에 처리하도록 지시하므로 버퍼의 마지막 쉼표만 바꾸면 됩니다.

안타깝게도 첫 번째 쉼표( s/,//) 또는 42번째 쉼표( s/,//42)는 쉽게 제거할 수 있지만 마지막 쉼표는 제거할 수 없습니다(유사한 작업은 s/,//$구현되지 않음).

따라서 우리는 "탐욕"을 활용합니다 *. .*가능한 한 많은 문자가 일치하므로 .*,마지막 쉼표까지의 모든 문자가 일치됩니다. 하지만 우리는 마지막 쉼표만 제거하고 싶기 때문에 다른 모든 항목을 으로 묶고 \(\)교체 시 해당 부분을 로 재사용할 수 있습니다 \1.

-z해당 옵션이 없으면 sed버퍼의 모든 라인을 수동으로 수집해야 합니다.

echo "$json" | sed 'H;1h;$!d;x;s/\(.*\),/\1/'

답변2

이는 JSON 관련 문제입니다. 마지막 배열 항목 뒤에 쉼표가 오면 ,JSON 유효성 검사기는 해당 항목이 이라는 오류를 발생시킵니다 Expected another array element at line ....

노력하다해결책:

예제 json 파일 input.json(잘못됨):

[
  {
    "name": "a"
  },
  {
    "name": "b",
    "keys": [
        1,2,3,
    ]
  },
  {
    "name": "c"
  },
]

awk -v RS= '{ gsub(/,[[:space:]]*]/, "\n]", $0) }1' input.json | jq '.'

출력(파이프)):

[
  {
    "name": "a"
  },
  {
    "name": "b",
    "keys": [
      1,
      2,
      3
    ]
  },
  {
    "name": "c"
  }
]

답변3

,]인스턴스를 로 교체하면 어떨까요 ]?

echo "$json" | sed 's/,]/]/'

관련 정보