2017-02-18 4 views
0

Так я бег randomfile, который может принимать несколько аргументов ($ 1 и $ 2) не показаны, а затем что-то делает с аргументом, передаваемым ...Добавление номеров с петлей при использовании водопроводного выхода

с 3-го аргумента , я должен искать $ 3 (или не $ 3) в file1 и добавить количество экземпляров этого в file2 ...

это работает отлично:

cat file1 | grep $3 | wc -l | while read line1; do echo $3 $line1 > file2; done 

cat file1 | grep -v $3 | wc -l | while read line2; do echo not $3 $line2 >> file2; done 

Теперь я пытаюсь читать file2, что держит экземпляры поиска, я хочу получить числа в файле, получить сумму, затем добавить в файл2. Так, например, если $ 3 был «ребенок»:

file2 бы, содержа-

baby 30 
not baby 20 

, а затем я хочу, чтобы получить сумму от 20 до 30 лет, и добавить к этому же file2, так что это выглядит как-

baby 30 
not baby 20 
total 50 

Это то, что я есть в данный момент:

cat file2 | grep -o '[0-9]*' | while read num ; do sum=$(($sum + $num));echo "total $sum" >> file2; done 

мой file2 заканчивает с двумя линиями для сумм, где один из них - то, что мне нужно -

baby 30 
not baby 20 
total 30 
total 50 

Что я здесь пропустил?

+0

Тема: Заменить 'while read line1; do echo $ 3 $ line1> file2; done' с 'while readline1; do echo $ 3 $ line1; done> file2 ', когда цикл while выполняется более одного раза: второй запуск перезапишет результаты dirst. Еще лучше: 'IFS = read -r line1; do echo "$ 3 $ {line1}"; done> file2 '. –

ответ

1

Это происходит потому, что ваше эхо находится внутри цикла for.

Очевидным решением было бы перемещение этого вне цикла for, но если вы попробуете это, вы обнаружите, что сумма $ sum не установлена, это потому, что циклы while и pipe фактически порождаются как их собственные процессы. Вы можете решить эту проблему с помощью брекетов ({}) группировать команды:

cat file2 | grep -o '[0-9]*' | { while read num ; do sum=$(($sum + $num)); done; echo "total $sum" >> file2; }

Другие ответы действительно указывают лучшие способы сделать это, но это, надеюсь, поможет вам понять, что происходит.

+0

Этот ответ действительно объясняет, что происходит с OP. Отлично. Код OP был скорее криком для улучшения, поэтому другие ответы также ценны (я надеюсь) для OP. – linuxfan

+0

Это то, что мне нужно. Большое вам спасибо за разъяснение! – noname

0

cat file1 | grep $ 3 | wc -l | при чтении строки1; do echo $ 3 $ line1> file2; сделано

Если вы хотите, чтобы сосчитать экземпляры $ 3, вы можете использовать опцию -c Grep из, избегая трубы для WC (1). Более того, было бы лучше процитировать $ 3. Наконец, вам не нужен цикл для чтения счета (либо из wc или grep): это одна строка! Таким образом, ваш код выше может быть записана следующим образом:

count=$(grep -c "$3" file1) 
echo $count $3 >file2 

Второй Grep будет точно так же, как и раньше:

count=$(grep -vc "$3" file1) 
echo $count $3 >>file2 

Теперь вы должны иметь промежуточный результат:

30 детей
20 не детей

Обратите внимание, что я отменил два термина, счетчик и шаблон; это потому, что мы знаем, что граф - это одно слово, но шаблон может быть больше слов. Поэтому, записывая сначала счет, у нас есть четко определенный формат: «count, then all the остальное».

Третий цикл может быть записана следующим образом:

while read num string; do 
    # string is filled with all the rest on the line 
    let "sum = $sum + $num" 
done < file2 
echo "$sum total" >> file2 

Есть другие способы обобщающие общей суммы; если необходимо, вы также можете отменить условия окончательного файла, как и ваш оригинал, - это можно сделать, снова используя другой файл.

+0

Когда вы используете 'count2 = $ (grep -vc" $ 3 "file1)', вы можете использовать '((sum = count + count2))'. –

+0

@WalterA Конечно, да. Я хотел придерживаться предыдущего стиля (писать в файлы, а затем перечитывать все) :-) – linuxfan