문제는 어떻게 열과 값을 원하는 순서로 재배치하느냐는 것이다.
입력하다
"a":"val1","c":"val2","b":"val3","d":"val4"
"a":"val1","b":[],"c":"val3","d":"val4"
"a":"val1","d":["val2","val32],"c":"val3","b":"val4"
"d":"val1","a":"val2","c":"val3","b":"val4"
예상되는 출력은 a, b, c, d 및 해당 값이어야 합니다.
"a":"val1"|"b":"val3"|"c":"val2"|"d":"val4"
"a":"val1"|"b":[]|"c":"val3"|"d":"val4"
"a":"val1"|"b":"val4"|"c":"val3"|"d":["val2","val32]
"a":"val2"|"b":"val4"|"c":"val3"|"d":"val1"
답변1
귀하의 질문은 시간이 지남에 따라 꽤 많이 바뀌었으므로 세 가지 다른 질문에 답해 보겠습니다.
당신의 시도 1
귀하의 awk
명령은 에서 발생하려고 합니다 . 각 줄에 한 번만 발생하므로 sum admin:
필드만 인용할 수 있습니다 .$1
$2
admin:
다음을 찾고 있을 수도 있습니다.
printf '%s\n' '"_id":"asc" ,"name":"enygren" ,"admin":[] ,"creat":"date3"' |
sed 's/"//g' |
awk -F' ,' -v OFS='|' '{if ($2~/name:/){print $1,$3,$4,$2} else {$1=$1; print $0}}'
물론 이는 좋은 생각이 아닐 수도 있습니다 /name:/
.포함하다 name:
, 정확한 라벨 뿐만이 아닙니다 name:
.
아무튼 이건 같네요XY 문제.
열 재정렬
awk
다음은 열이 다음에서 왔다고 가정하여 열을 선택하고 다시 정렬하도록 사용자 정의할 수 있는 솔루션 입니다.구분된 텍스트 파일.
입력 데이터의 필드에는 "
또는 가 포함될 수 없다고 가정합니다 ,
. 귀하가 게시한 코드에 따르면 이는 합리적으로 들리지만1 실제로 는 그렇지 않은 것 같습니다. 구조화된 데이터 작업을 위해 특별히 설계된 일부 도구(아래 참조)를 사용해야 합니다.csvkitCSV의 경우 또는잭JSON의 경우(감사합니다.키위팁).
스크립트가 주어지면 prog_file
:
BEGIN {
# Create an array of labels for the fileds you want
# to keep, in the order you want to print them
labels[1] = "\"_id\""
labels[2] = "\"admin\""
labels[3] = "\"creat\""
labels[4] = "\"name\""
}
{
# Split any field on ":" and make an array of
# full fields indexed by their label.
# This assumes labels DO NOT CONTAIN any ":"
for ( i=1; i<=NF; i++ ) {
split($i, chunks, ":")
fields[chunks[1]] = $i
}
# Reset the record
$0 = ""
# Re-build the record with only the fields
# whose labels are in the array we defined in
# the BEGIN block.
# Explicitly use "4" as the upper bound because
# POSIX does not specify the order in which
# "for (var in array)" assigns indexes to var
for ( i=1; i<=4; i++ ) {
$i = fields[labels[i]]
}
# Strip any double quote
gsub("\"","")
print $0
}
입력 2 :
"_id":"123" ,"admin":[src] ,"creat":"date1" ,"name":"dedu"
"_id":"2w3" ,"admin":[analise] ,"creat":"date2" ,"name":"csv"
"_id":"asc" ,"name":"enygren" ,"admin":[] ,"creat":"date3"
"_id":"scd" ,"admin":[] ,"creat":"date4" ,"name":"tzpi"
옮기다:
awk -v FS=' ,' -v OFS='|' -f prog_file input_file
3을 제공합니다 :
_id:123|admin:[src]|creat:date1|name:dedu
_id:2w3|admin:[analise]|creat:date2|name:csv
_id:asc|admin:[]|creat:date3|name:enygren
_id:scd|admin:[]|creat:date4|name:tzpi
데이터 형식 처리
이것마지막질문에서 편집한 입력 데이터 샘플이 구분된 텍스트 파일에서 가져온 것으로 보이지 않습니다. JSON 개체 목록처럼 보입니다.
사람이 읽을 수는 있지만,JSON는데이터형식을 지정하고 다른 접근 방식이 필요합니다. 실제로 위의 awk
솔루션은 이 입력에 대해 작동하지 않습니다.
비트 구조를 추가한 후 예제를 유효한 JSON으로 변환(반환?)할 수 있습니다.
$ cat file
"a":"val1","c":"val2","b":"val3","d":"val4"
"a":"val1","b":[],"c":"val3","d":"val4"
"a":"val1","d":["val2","val32"],"c":"val3","b":"val4"
"d":"val1","a":"val2","c":"val3","b":"val4"
"
(참고로 빠진 부분은 "d":["val2","val32]
철자 오류인 줄 알고 그대로 사용했습니다 "d":["val2","val32"]
.)
$ sed 's/^/{/; s/$/},/; 1 s/^/[/; $ s/,$/]/' file >tmpfile
$ cat tmpfile
[{"a":"val1","c":"val2","b":"val3","d":"val4"},
{"a":"val1","b":[],"c":"val3","d":"val4"},
{"a":"val1","d":["val2","val32"],"c":"val3","b":"val4"},
{"d":"val1","a":"val2","c":"val3","b":"val4"}]
그런 다음 안전한 접근 방식은 JSON 프로세서를 사용하여 jq
데이터를 필터링하고 재정렬하는 것입니다.
$ jq -r '.[] | {a: .a, b: .b, c: .c, d: .d} | @text' tmpfile
{"a":"val1","b":"val3","c":"val2","d":"val4"}
{"a":"val1","b":[],"c":"val3","d":"val4"}
{"a":"val1","b":"val4","c":"val3","d":["val2","val32"]}
{"a":"val2","b":"val4","c":"val3","d":"val1"}
남은 개폐 브래킷을 제거하는 것은 간단하고 안전하며,안전하지 않을 거야예제 출력과 정확히 일치하도록 큰따옴표( "
)를 맹목적으로 제거하거나 쉼표를 파이프( ,
→ )로 바꾸십시오.|
질문에서 1개개정 번호 4도착하다7번.
2 질문의 마지막 부분에서 추론개정 번호 6.
3 문제의 관점에서개정 번호 6.
답변2
귀하의 시도를 무시했다면 죄송합니다. 나에게 그것은 너무 복잡해 보이고 많은 스크립트와 도구를 통한 파이핑이 필요합니다.
내가 아는 한, 열의 순서는 정확합니다. 단 idxg_name
, 끝에 있어야 합니다. 따라서 간단히 다음을 수행하는 것이 좋습니다.
sed 's/"//g;s/\(,idxg_name:[^,]*\)\(.*\)/\2\1/' yourfile
- 이
s/"//g
섹션에서는"
이미 수행한 작업을 제거합니다. ,idxg_name:[^,]*
쉼표로 시작하여 다음 쉼표 앞의 모든 항목을 포함하여 필드를 일치시킵니다idxg_name
. (이름에 쉼표가 포함되어 있으면 실패합니다. 그런 경우 쉼표가 안에 있는지 여부를 고려하여 상황이 더 복잡해집니다.""
).*
나머지 줄 과 일치하고- 대체는
\2\1
내부 두 부분의 순서를 변경하여\(\)
이름 필드를 줄 끝에 배치합니다. 완벽한.