Скрипт перечитывает аргументы - PullRequest
1 голос
/ 30 ноября 2008

Когда я поставлю скрипт с аргументом: hi [123] .txt, он будет делать то, что я хочу. Но если я укажу символ подстановки (hi * .txt), он будет перечитывать некоторые файлы.

Мне было интересно, как изменить этот скрипт, чтобы решить эту глупую проблему:

#!/bin/sh

count="0"
total="0"
FILE="$1"  #FILE specification is now $1 Specification..

for FILE in $@
do
  #if the file is not readable then say so
     if [ ! -r $FILE ];
         then
         echo "File: $FILE not readable"
     exit 0
     fi


# Start processing readable files
  while read line
          do

             if [[ "$line" =~ ^Total ]];
                 then
                   tmp=$(echo $line | cut -d':' -f2)

                   total=$(expr $total + $tmp)

                   echo "$FILE (s) have a total of:$tmp "
                   count=$(expr $count + 1)

             fi

        done < $FILE
done
echo " Total is: $total"
echo " Number of files read is:$count"

Ответы [ 4 ]

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

Это кажется избыточным:

FILE="$1"  #FILE specification is now $1 Specification..

for FILE in $@
  ...

Первоначальное назначение быстро перезаписывается.

В целом эта задача лучше подходит для языка обработки строк, такого как awk или perl.

Рассмотрим что-то вроде этого сценария awk:

BEGIN{
   TOTAL=0;
   COUNT=0;
   FS=':';
}
/^Total/{
   TOTAL += $2;
   COUNT++;
   printf("File '%s' has a total of %i",FILENAME,TOTAL);
}
END{
   printf("Total is %i",TOTAL);
   printf("Number of files read is%i",COUNT);
}
1 голос
/ 30 ноября 2008

Я не знаю, что с ним не так, но одна маленькая вещь, которую я заметил:

Измените for FILE in $@ на for FILE in "$@". Потому что, если файлы имеют встроенные пробелы, вы теперь на безопасном пути. Затем он расширится до "$1" "$2" ..., вместо $1 $2 ... (и помните, что везде, где вы используете $ FILE, тоже не забывайте "" его).

И что говорят другие, вам не нужно инициализировать FILE перед тем, как войти в цикл. Он будет установлен на каждое из имен файлов расширенных позиционных параметров в цикле for автоматически.

Тем не менее, я бы пошел со скриптом awk следующим образом:

awk -F: '
/^Total/ { 
    total += $2
    # count++ not needed. see below
    print FILENAME "(s) have a total of: " $2
} 

END { 
    print "Total is: " total
    print "Number of files read is: " (ARGC-1) 
}' foo*.txt

Обратите внимание, что когда файл содержит несколько строк «^ Count», вы действительно скажете, что прочитали больше файлов, чем фактически прочитали, если бы использовали count, чтобы указать количество прочитанных файлов.

0 голосов
/ 30 ноября 2008

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

echo "$0: file $FILE not readable" 1>&2

1 теоретически не требуется (хотя я помню проблемы с реализацией оболочки в Windows, если она была опущена). Хорошей идеей будет повторение имени сценария '$0' в начале сообщения об ошибке - оно облегчает отслеживание ошибок позже, когда ваш сценарий используется в других контекстах.

Я полагаю, что этот однострочный Perl делает то, что вам нужно.

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

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

0 голосов
/ 30 ноября 2008

Как насчет этого решения:

for FILE in `/bin/ls $@`
do
. . .

Это эффективно устранит дубликаты, потому что /bin/ls hi1.txt hi1.txt hi1.txt должен показывать hi1.txt только один раз.

Хотя я не уверен, почему он перечитывает файлы. Расширение подстановочного знака должно включать каждый файл только один раз. У вас есть файлы, соответствующие hi*.txt, которые являются ссылками на файлы, соответствующие hi[123].txt?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...