Как мне заставить мой bash скрипт работать? - PullRequest
0 голосов
/ 29 ноября 2008

Мой bash-скрипт не работает так, как я хочу:

#!/bin/bash

total="0"
count="0"
#FILE="$1" This is the easier way
for FILE in $*
do
    # Start processing all processable files
    while read line
    do
        if [[ "$line" =~ ^Total ]];
        then
            tmp=$(echo $line | cut -d':' -f2)
            count=$(expr $count + 1)
            total=$(expr $total + $tmp)
        fi     
    done < $FILE
done
echo "The Total Is: $total"
echo "$FILE"

Есть ли другой способ изменить этот скрипт так, чтобы он считывал аргументы в $1 вместо $FILE? Я пытался использовать цикл while:

while [ $1 != "" ]
  do ....
done

Также, когда я реализую это, код повторяется. Есть ли способ исправить это?

Другая проблема, с которой я сталкиваюсь, заключается в том, что когда у меня несколько файлов hi*.txt, это дает мне дубликаты. Зачем? У меня есть файлы типа hi1.txt hi1.txt~, но файл тильды имеет 0 байт, поэтому мой сценарий не должен ничего искать.


То, что у меня есть, хорошо, но может быть улучшено. Я ценю ваши предложения по awk, но в настоящее время я не программист Unix.

Strager: файлы, которые генерирует мой текстовый редактор, автоматически не содержат ничего ... он имеет 0 байтов ... Но да, я пошел дальше и удалил их просто для уверенности. Но нет, мой сценарий на самом деле читает все дважды. Я полагаю, он снова зацикливается, когда это действительно не нужно. Я пытался заставить замолчать это действие с помощью команд выхода. Но не удалось.

while [ "$1" != "" ]; do
    # Code here

    # Next argument
    shift
done

Этот код довольно приятный, но я указываю все возможные команды одновременно. Пример: привет [145] .txt При наличии будет читать все три файла одновременно. Предположим, пользователь вводит привет * .txt; Затем я дважды читаю все свои привет-файлы и затем снова добавляю.

Как я могу кодировать его так, чтобы он считывал мои файлы (только один раз) по спецификации hi * .txt? Я действительно думаю, что это из-за отсутствия $ 1.

Ответы [ 3 ]

2 голосов
/ 29 ноября 2008

Похоже, вы пытаетесь сложить итоги из строк, помеченных как «Итого», в предоставленных файлах. Всегда полезно указать, что вы пытаетесь сделать, а также то, как вы пытаетесь это сделать (см. Как задавать вопросы «Умным путем» ).

Если это так, то вы делаете примерно так же сложно, как я вижу. Что было не так с:

grep '^Total:' "$@" |
cut -d: -f2 |
awk '{sum += $1}
     END { print sum }'

Это не распечатывает "Итого" и т.д .; и непонятно, почему вы выводите $ FILE в конце вашей версии.

Вы можете использовать Perl или любую другую подходящую программу вместо awk; Вы можете выполнить всю работу на Perl или Python - действительно, cut работа может быть выполнена с помощью awk:

grep "^Total:" "$@" |
awk -F: '{sum += $2}
         END { print sum }'

В целом, всю работу можно выполнить с помощью awk:

awk -F: '$1 ~ /^Total/ { sum += $2 }
         END { print sum }' "$@"

Код на Perl не будет намного сложнее, и результат может быть быстрее:

perl -na -F: -e '$sum += $F[1] if m/^Total:/; END { print $sum; }' "$@"

При переборе аргументов имени файла, предоставляемых в сценарии оболочки, вы должны использовать '"$@"' вместо '$*', так как последняя запись не сохраняет пробелы в именах файлов.

Ваш комментарий о '$1' сбивает меня с толку. Вы могли бы попросить прочитать из файла, имя которого в $1 на каждой итерации; это делается с помощью:

while [ $# -gt 0 ]
do
     ...process $1...
     shift
done

НТН!

1 голос
/ 29 ноября 2008
while [ "$1" != "" ]; do
    # Code here

    # Next argument
    shift
done

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

1 голос
/ 29 ноября 2008

Если вы определите функцию, она получит аргумент в виде $ 1. Почему $ 1 для вас более ценен, чем $ FILE?

#!/bin/sh

process() {
    echo "doing something with $1"
}

for i in "$@" # Note use of "$@" to not break on filenames with whitespace
do
    process "$i"
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...