목록을 반복하여 가장 잘 해결하는 방법을 잘 모르는 흥미로운 문제가 있습니다. 다음 형식으로 -
element, date, unixTime, value
CZ, 12/27/2007 15:55, 1198788900, 42346
CZ, 12/27/2007 17:30, 1198794600, -10543
I, 12/27/2007 19:05, 1198800300, 4475
각 고유 요소와 각 날짜를 반복하여 "값" 열의 부호를 얻고 싶습니다. 예를 들어, 2007년 12월 27일에 CZ와 I에 대해 각각 하나씩 2개의 행을 원합니다. 하루의 마지막 부분에 발생하는 행이 음수 값을 갖기 때문에 CZ는 음수이고 I는 양수입니다. 그런 다음 12/28, 12/29 등과 같은 다양한 요소에 대해 이 작업을 다시 수행합니다. 중첩된 for 루프를 사용하여 반복할 수 있지만 파일이 크기 때문에 날짜별로 정렬된 파일을 한 번만 반복하는 방법을 찾는 것이 더 나을 것입니다. 이 작업을 가장 효율적으로 수행하는 방법에 대해 약간 혼란 스럽습니다. bash가 이에 적합한지, 아니면 Perl이나 Python과 같은 다른 언어가 적합한지 잘 모르겠습니다.
답변1
입력 데이터를 호출해 봅시다부자:
echo 'element, date, unixTime, value
CZ, 12/27/2007 15:55, 1198788900, 42346
CZ, 12/27/2007 17:30, 1198794600, -10543
I, 12/27/2007 19:05, 1198800300, 4475' > foo
달리기암소 비슷한 일종의 영양 datamash
존재하다부자:
datamash -t, --header-in -g 1 last 4 < foo
산출:
CZ, -10543
I, 4475
좀 더 공식적인 스위치 이름을 사용하면 datamash
위 내용이 더 명확해질 수 있으며 헤더 이름을 추가했습니다(계산된 열이 불편한 경우).
datamash --field-separator=',' --header-in --group=element last " value" < foo
답변2
@agc가 원하는 출력을 올바르게 해석했다고 가정하면 awk
일반 이전 버전을 사용할 수 있습니다.
awk -F, 'NR>1{a[$1]=$4}END{for(x in a){print x","a[x]}}' foo
CZ, -10543
I, 4475
답변3
파일이 미리 정렬되어 있다는 사실 을 통해 sed
.sed pattern space
2 lines
sed -e '
$!{
N
/^\([^,]*\),[[:space:]]\{1,\}\([^[:space:]]\{1,\}\)[[:space:]].*[[:space:]]\([^[:space:]]\{1,\}\)\n\1,[[:space:]]\{1,\}\2[[:space:]]/D
}
s/^\([^,]*\),[[:space:]]\{1,\}\([^[:space:]]\{1,\}\)[[:space:]].*[[:space:]]\([^[:space:]]\{1,\}\)\(\n\)/\1 \3\4/
/\n/!s/^\([^,]*\),[[:space:]]\{1,\}\([^[:space:]]\{1,\}\)[[:space:]].*[[:space:]]\([^[:space:]]\{1,\}\)/\1 \3/
P;D
' yourfile
간단히
We always keep 2 lines in the pattern space and note the time when there
is a change in the 1st field. So long as we keep encountering the same
first two fields, we keep chopping off the previous line and reading in
the next. And on a transition we print the 1st and last fields of the
previous line, print it, remove upto the newline, and go back for more
with whats left in the pattern space.