다음과 같은 json 파일이 있습니다.
[
{
"key": "alt+down",
"command": "-editor.action.moveLinesDownAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "alt+f12",
"command": "editor.action.peekDefinition",
"when": "editorHasDefinitionProvider && editorTextFocus && !inReferenceSearchEditor && !isInEmbeddedEditor"
}
]
// {
// "key": "ctrl+shift+d",
// "command": "workbench.action.toggleMaximizedPanel"
// },
// {
// "key": "ctrl+shift+d",
// "command": "-workbench.view.debug",
// "when": "viewContainer.workbench.view.debug.enabled"
// }
이 파일을 정렬하고 싶습니다.
jq
//
줄 시작 부분에 하나가 있으면 유효한 json이 아니기 때문에 오류가 발생합니다.
따라서 이 파일을 정렬하기 위해 내가 생각해낸 명령은 다음과 같습니다.
grep -v '^[ ]*//' keybindings.json | jq 'sort_by(.key)'
그러나 나는 주석이 달린 줄을 버리고 싶지 않습니다. 따라서 주석 처리된 줄을 얻기 위해 내가 생각해낸 명령은 다음과 같습니다.
grep '^[ ]*//' keybindings.json
이제 내 문제를 해결하기 위해 간단히 할 수 있는 일은 다음과 같습니다.
#!/bin/bash
SORTED_JSON=$(grep -v '^[ ]*//' keybindings.json | jq 'sort_by(.key)')
COMMENTED_JSON=$(grep '^[ ]*//' keybindings.json)
echo "$SORTED_JSON" >keybindings.json
echo "$COMMENTED_JSON" >>keybindings.json
하지만 문제가 있습니다!
이 작업은 하나의 명령으로 수행해야 합니다. 이는 vscode 설정을 통해 이 작업을 수행하기 때문입니다.
"filterText.commandList": [
{
"name": "Sort VSCode Keybindings",
"description": "Sorts keybindings.json by keys. Select everything except the comment in fist line. Then run this command",
"command": "jq 'sort_by(.key)'"
}
]
선택한 텍스트를 표준 입력으로 가져와서 command
처리하고, 처리된 텍스트를 출력합니다.
그래서 제가 이해한 바에 따르면 stdin을 두 번 읽어야 합니다(한 번 grep -v '^[ ]*//' | jq 'sort_by(.key)'
, 또 다시 grep '^[ ]*//'
). 두 명령의 출력을 stdout에 추가합니다.
이 문제를 어떻게 해결할 수 있나요?
업데이트 1:
나는 그들 모두를 시도했다
cat keybindings.json| {grep -v '^[ ]*//' | jq 'sort_by(.key)' ; grep '^[ ]*//'}
그리고
cat keybindings.json| (grep -v '^[ ]*//' | jq 'sort_by(.key)' ; grep '^[ ]*//')
주석 줄은 표시되지 않습니다.
업데이트 2:
다음은 내가 기대했던 것과 가까운 것 같습니다. 그러나 여기서는 주석 처리된 줄이 주석 처리되지 않은 줄 앞에 옵니다.
$ cat keybindings.json| tee >(grep -v '^[ ]*//' | jq 'sort_by(.key)') >(grep '^[ ]*//') > /dev/null 2>&1
// {
// "key": "ctrl+shift+d",
// "command": "workbench.action.toggleMaximizedPanel"
// },
// {
// "key": "ctrl+shift+d",
// "command": "-workbench.view.debug",
// "when": "viewContainer.workbench.view.debug.enabled"
// }
[
{
"key": "alt+down",
"command": "-editor.action.moveLinesDownAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "alt+f12",
"command": "editor.action.peekDefinition",
"when": "editorHasDefinitionProvider && editorTextFocus && !inReferenceSearchEditor && !isInEmbeddedEditor"
}
]
업데이트 3:
cat keybindings.json| (tee >(grep '^[ ]*//'); tee >(grep -v '^[ ]*//' | jq 'sort_by(.key)'))
또는,
cat keybindings.json| {tee >(grep '^[ ]*//'); tee >(grep -v '^[ ]*//' | jq 'sort_by(.key)')}
또한 업데이트 3과 동일한 출력을 제공하는 것 같습니다(주석 처리되지 않은 행 앞에 주석 처리된 행).
답변1
주석 줄과 주석이 아닌 줄을 혼합하여 삽입하는 방법은 없습니다. 이를 별도의 블록으로 처리하고 별도로 처리해야 합니다.
주석 줄을 먼저 출력해도 괜찮다면 awk
다음과 같이 사용할 수 있습니다.
awk '{ if ($0 ~ /^ *\/\//) { print } else { print | "jq \"sort_by(.key)\"" } }' keybindings.json
하지만 주석 줄이 끝에 나타나기를 원하므로 주석 줄을 저장하고 나중에 출력해야 합니다.
awk '
# Define a convenience variable for the jq process
BEGIN {
jq = "jq \"sort_by(.key)\""
}
# Each line hits this. Either we save the comment or we feed it to jq
{
if ($0 ~ /^ *\/\//) { c[++i] = $0 }
else { print | jq }
}
# Close the pipe to get its output and then print the saved comment lines
END {
close (jq);
for (i in c) { print c[i] }
}
' keybindings.json
이제 당신의 "명령 하나로 이 작업을 수행해야 합니다.". 자신만의 명령(프로그램, 스크립트)을 생성하는 것을 방해하는 것은 아무것도 없다는 것을 기억하십시오. 필요한 명령 세트를 파일에 넣고 해당 파일을 실행 가능하게 만든 다음 . .나는 사용 $PATH
하고 있으며 내 및 .$HOME/bin
export PATH="$PATH:$HOME/bin"
~/.bash_profile
~/.profile
답변2
주석을 문자열로 변환하고 배열을 정렬한 다음 주석 문자열을 다시 주석으로 변환합니다.
주석을 문자열로 변환하는 작업은 다음과 같습니다.
//
(선택적 들여쓰기 및 공백 포함)로 시작하는 줄을 감지합니다 ."
이 줄에 있는 모든 항목을\"
, 및- 이 줄을 큰따옴표로 묶으세요.
sed '\:^ *//: { s/"/\\"/g; s/.*/"&"/; }'
그런 다음 배열을 정렬합니다.
jq 'if type == "array" then sort_by(.key) else . end'
마지막으로 주석 문자열을 다시 주석으로 변환합니다.
"//
(및 사이에 선택적 공백 포함)로 시작하고 다음으로 끝나는 줄을 감지합니다 ."
//
"
- 이 줄의 첫 번째 줄
"
과"
마지막 줄 을 삭제하세요. - 각각을
\"
로 교체하세요"
.
sed '\:^"\( *//.*\)"$: { s//\1/; s/\\"/"/g; }'
표준 입력에서 완전히 읽는 파이프:
sed '\:^ *//: { s/"/\\"/g; s/.*/"&"/; }' |
jq 'if type == "array" then sort_by(.key) else . end' |
sed '\:^"\( *//.*\)"$: { s//\1/; s/\\"/"/g; }'
이는 데이터에 이스케이프된 큰따옴표가 아직 포함되어 있지 않다고 가정합니다.
답변3
나는 약간의 연구를 했기 때문에 내 질문에도 대답하고 싶었습니다. 한 줄 명령의 경우:
cat keybindings.json | (tee /tmp/program-code-binding.json | grep -v '^[ ]*//' | jq 'sort_by(.key)'; cat /tmp/program-code-binding.json | grep '^[ ]*//')
스크립트를 사용하려면 다음을 수행하십시오.
#!/bin/bash
THESTDIN=$(cat)
SORTED_JSON=$(echo "$THESTDIN" | grep -v '^[ ]*//' | jq 'sort_by(.key)')
COMMENTED_JSON=$(echo "$THESTDIN" | grep '^[ ]*//')
echo "$SORTED_JSON"
echo "$COMMENTED_JSON"
이 스크립트에는 극단적인 경우가 있습니다.THESTDIN=$(cat)
파이프에 아무것도 없으면 무기한 매달립니다.. 이 문제를 해결하기 위해 스크립트는 실제로 다음과 같습니다.
#!/bin/bash
__=""
THESTDIN=""
read -N1 -t1 __ && {
(( $? <= 128 )) && {
IFS= read -rd '' _stdin
THESTDIN="$__$_stdin"
}
}
SORTED_JSON=$(echo "$THESTDIN" | grep -v '^[ ]*//' | jq 'sort_by(.key)')
COMMENTED_JSON=$(echo "$THESTDIN" | grep '^[ ]*//')
echo "$SORTED_JSON"
echo "$COMMENTED_JSON"