LINUX.ORG.RU

Обработать файл


1

2

Привет, лор!
Есть файл, состоящий из записей вида:

<число>,<столбец1>
<число>,<столбец1>
<число>,<столбец1>
<число>,<столбец1>

Надо обработать его следующим образом:
Если данные в <столбец1> совпадают, то просуммировать <число> и заменить строки с совпадающими данными на одну строку.

То есть:

123,abcdf
100,abcdf
200,abcdf
100,xyzf

после обработки будет выглядеть так:
423,abcdf
100,xyzf

Буду рад любой помощи)

могу на PHP наговнокодить, но будет не очень шустро, сойдет?

xorik ★★★★★ ()
cat file | perl -e 'while (<>) { /(\d+),(\w+)/; $ec{$2}+=$1; } foreach(keys %ec) { print "$ec{$_},$_\n" };'
redgremlin ★★★★★ ()
Ответ на: комментарий от teamfighter
#!/bin/sh
IN=/tmp/in

LINES=`wc -l $IN`
LINES=${LINES/ */}


LINE=`sed -n 1p $IN`
NUM_PREV=${LINE/,*/}
STR_PREV=${LINE/*,/}

for i in `seq 2 $LINES` 
do 
  LINE=`sed -n ${i}p $IN`
  NUM_CUR=${LINE/,*/}
  STR_CUR=${LINE/*,/}
  if [ ${STR_CUR} = ${STR_PREV} ]
  then
    NUM_PREV=$((${NUM_PREV} + ${NUM_CUR}))
  else
    echo ${NUM_PREV},${STR_PREV}
    NUM_PREV=${LINE/,*/}
    STR_PREV=${LINE/*,/}
  fi
done
echo ${NUM_PREV},${STR_PREV}

В файле /tmp/in указанные вами входные данные:

123,abcdf
100,abcdf
200,abcdf
100,xyzf
В качестве разделителя блоков используется запятая ",".

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 1)
Ответ на: комментарий от teamfighter

Здесь указали правильный файл?

IN=/tmp/in
У вас Linux?

$./sc.sh 
423,abcdf
100,xyzf

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 1)
Ответ на: комментарий от teamfighter

Ты точно ему то, что надо скармливаешь?

$ cat test
123,abcdf
100,abcdf
200,abcdf
100,xyzf
$ cat test | perl -e 'while (<>) { /(\d+),(\w+)/; $ec{$2}+=$1; } foreach(keys %ec) { print "$ec{$_},$_\n" };'
423,abcdf
100,xyzf

redgremlin ★★★★★ ()
Ответ на: комментарий от kostik87

В общем, как всегда поменяли задачу «на лету» Теперь в файле 4 колонки, разделенные запятыми. Наговнокодил нечто такое:

#!/bin/bash
##VAR DETERMINATION
input=./test.csv #input file
str_count=`cat $input|wc -l` #string counter
##Arrays of data
array_col_0=(`cat $input|awk -F , ' {print $1}'`)
array_col_1=(`cat $input|awk -F , ' {print $2}'`)
array_col_2=(`cat $input|awk -F , ' {print $3}'`)
array_col_3=(`cat $input|awk -F , ' {print $4}'`)
for i in `seq 0 $[ $str_count - 1 ]`; do

if [ "${array_col_1[$i]}" == "${array_col_1[$i+1]}" ] && [ "${array_col_2[$i]}" == "${array_col_2[$i+1]}" ] && [ "${array_col_3[$i]}" == "${array_col_3[$i+1]}" ]
then
echo "We got some matches here, yeah!"
else echo "no matches"
fi
done

Но сопсна застрял на проверки существования дубликатов. То есть кусок

if [ "${array_col_1[$i]}" == "${array_col_1[$i+1]}" ] && [ "${array_col_2[$i]}" == "${array_col_2[$i+1]}" ] && [ "${array_col_3[$i]}" == "${array_col_3[$i+1]}" ]

особого доверия не внушает.

teamfighter ()
Ответ на: комментарий от teamfighter
#!/bin/bash

function data() {
cat <<EOF
123,ab,cd,f
100,ab,cd,f
200,abc,d,f
100,x,y,zf
EOF
}

data | awk -F, '{
  n=sprintf("%s,%s,%s",$2,$3,$4);
  M[n]+=$1
}
END{for(k in M) printf "%i,%s\n",M[k],k }'
anonymous ()
Ответ на: комментарий от teamfighter
#!/usr/bin/python3

val={}
for line in open('data.csv'):
	n, key = line.strip().split(',', 1)
	val[key] = int(n) + val.get(key, 0)
	
for key, n in val.items():
	print(str(n) + ',' + key)

Для любого количества колонок.

fffgh ()

Эксель/librecalc, сводная таблица — тривиально.

habamax ★★ ()
Ответ на: комментарий от teamfighter

Это не Ъ

Для несложного анализа данных — очень даже тру. Минимум затрат при сравнительно небольших объемах данных.

habamax ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.