2014-09-09 4 views
1

Это, вероятно, довольно простой, я хочу прочитать в файле вхождения.Чтение файла в сценарии оболочки и выбор раздела строки

Затем программа должна найти все вхождения "CallTilEdb" в файле Hendelse.logg:

 
CallTilEdb   8 
CallCustomer  9 
CallTilEdb   4 
CustomerChk  10 
CustomerChk  15 
CallTilEdb   16 

и подвести итоги, то в правой колонке. Для этого случая это будет 8 + 4 + 16, поэтому выход, который я хотел бы, будет 28.

Я не знаю, как это сделать, и это, насколько я получил с vistid.sh:

#!/bin/bash 
declare -t filename=hendelse.logg 
declare -t occurance="$1" 
declare -i sumTime=0 

while read -r line 
do 
    if [ "$occurance" = $(cut -f1 line) ]  #line 10 
    then 
     sumTime+=$(cut -f2 line) 
    fi 
done < "$filename" 

таким образом, исполнение в терминале будет

vistid.sh CallTilEdb

но ошибка Я получаю сейчас:

/home/user/bin/vistid.sh: line 10: [: unary operator expected
+0

Что такое "вхождение feks"? –

+0

@John Я пытался убрать вопрос, этот термин ушел. – Tomalak

+0

@JohnZwinck Я хотел написать occenture fex. (Пример) – Patidati

ответ

4

У вас хороший подход, но, возможно, вы могли бы использовать awk, чтобы сделать то же самое ... довольно быстро!

$ awk -v par="CallTilEdb" '$1==par {sum+=$2} END {print sum+0}' hendelse.logg 
28 

Это может выглядеть немного странно, если вы не использовали AWK до сих пор, но вот то, что он делает:

  • -v par="CallTilEdb" обеспечивают аргумент awk, так что мы можем использовать в качестве par переменная в скрипте. Вы также можете сделать -v par="$1", если вы хотите использовать переменную, предоставленную скрипту в качестве параметра.
  • $1==par {sum+=$2} это означает: если первое поле совпадает с содержимым переменной par, затем добавьте значение второго столбца в счетчик sum.
  • END {print sum+0} это означает: как только вы закончите обработку файла, распечатайте содержимое sum. +0 делает awk печать 0 в случае, если sum не был установлен ... то есть, если ничего не найдено.

В случае, если вы действительно хотите сделать это с Баш, вы можете использовать read с двумя параметрами, так что вы не должны использовать cut обрабатывать значения, вместе с некоторыми arithmetic operations к просуммировать значения:

#!/bin/bash 
declare -t filename=hendelse.logg 
declare -t occurance="$1" 
declare -i sumTime=0 

while read -r name value     # read both values with -r for safety 
do 
    if [ "$occurance" == "$name" ]; then # string comparison 
     ((sumTime+=$value))    # sum 
    fi 
done < "$filename" 

echo "sum: $sumTime" 

Так что это работает так:

$ ./vistid.sh CallTilEdb 
sum: 28 
$ ./vistid.sh CustomerChk 
sum: 25 
+0

Спасибо! Я буду пытаться оба подхода к практике, очень приятное и простое объяснение, на самом деле смысл :)! – Patidati

+0

@Patidati приятно читать это :) Примечание. Я добавил версию bash, потому что вы можете использовать 'read -r name value' и избавиться от всех этих' cut'. – fedorqui

+0

Это сработало (версия bash) Большое спасибо :) Будет проверять версию awk сейчас;) – Patidati

1

первую очередь вам необходимо изменить способ вызова вырезать:

$(echo $line | cut -f1) 

в строке 10 вы пропустите оценку:

if [ "$occurance" = $(echo $line | cut -f1) ] 

, то вы можете подытожить, выполнив:

sumTime=$[ $sumTime + $(echo $line | cut -f2) ] 

Но вы также можете использовать другой подход и поместить значение строки в массив, окончательный сценарий будет выглядеть так:

#!/bin/bash 
declare -t filename=prova 
declare -t occurance="$1" 
declare -i sumTime=0 

while read -a line 
do 
    if [ "$occurance" = ${line[0]} ] 
    then 
     sumTime=$[ $sumtime + ${line[1]} ] 
    fi 
done < "$filename" 

echo $sumTime 
+0

Просто захотелось быстро опубликовать, что я их читаю и пробовал;) – Patidati

+0

ОК :) Попытка первого апраха без массива будет пытаться последовать за массивом. Проблема в том, что в строке 10 я получаю эту ошибку: <Слишком много аргументов> В строке 12: <неожиданный EOF при поиске соответствия '] '> – Patidati

0

Awk перевода к подлиннику:

#!/bin/bash 
declare -t filename=hendelse.logg 
declare -t occurance="$1" 
declare -i sumTime=0 

sumtime=$(awk -v entry=$occurance ' 
            $1==entry{time+=$NF+0} 
            END{print time+0}' $filename) 
+0

Не нужно объявлять 'время'. Он определяется после его использования. Смотрите мой подход. – fedorqui

+0

Привет, если запись не найдена, то получается "void". +1 в любом случае – klashxx

+0

True! В этом случае удобно использовать 'END {print time + 0}', чтобы вы могли напечатать либо 'time', либо' 0'. – fedorqui

0

Для справки,

id="CallTilEdb" 
file="Hendelse.logg" 

sum=$(echo "0 $(sed -n "s/^$id[^0-9]*\([0-9]*\)/\1 +/p" < "$file") p" | dc) 
echo SUM: $sum 

печатает

SUM: 28 
  • в sed экстракт чисел из строк, содержащих заданный идентификатор, например CallTilEdb
  • и выводит их в формат number +
  • echo готовит строку таких 0 8 + 16 + 4 + p, что расчет в формате RPN
  • постоянному току сделать расчет

другой вариант:

sum=$(sed -n "s/^$id[^0-9]*\([0-9]*\)/\1/p" < "$file" | paste -sd+ - | bc) 
#or 
sum=$(grep -oP "^$id\D*\K\d+" < "$file" | paste -sd+ - | bc) 
  • СЕПГ (или Grep) экстракты и печатает только цифры
  • паста сделать строку, как number + number + number ()является разделителем)
  • bc сделать расчет

или Perl

sum=$(perl -slanE '$s+=$F[1] if /^$id/}{say $s' -- -id="$id" "$file") 
sum=$(ID="CallTilEdb" perl -lanE '$s+=$F[1] if /^$ENV{ID}/}{say $s' "$file") 
Смежные вопросы