2008-11-29 5 views
-1

Мой Баш скрипт не работает так, как я хочу, чтобы это:Как я могу заставить свой скрипт 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.txthi1.txt~, но файл тильды имеет 0 байт, поэтому мой скрипт не должен ничего находить.


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

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

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

    # Next argument 
    shift 
done 

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

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

+0

Пожалуйста, отформатируйте код немного лучше. Выделите все это и нажмите кнопку маленького кода или, по крайней мере, убедитесь, что в нем имеются четыре пробела. – Dustin 2008-11-29 00:28:00

ответ

1

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

#!/bin/sh 

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

for i in "[email protected]" # Note use of "[email protected]" to not break on filenames with whitespace 
do 
    process "$i" 
done 
1
while [ "$1" != "" ]; do 
    # Code here 

    # Next argument 
    shift 
done 

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

2

Похоже, вы пытаетесь скомпоновать итоговые значения из строк с надписью «Total:» в предоставленных файлах. Всегда полезно указать, что вы пытаетесь сделать, а также то, как вы пытаетесь это сделать (см. How to Ask Questions the Smart Way).

Если это так, то вы делаете это так же сложно, как я вижу. Что случилось с:

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

Это не распечатывает «Общее количество» и т. Д .; и непонятно, почему вы эхо $ FILE в конце своей версии.

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

grep "^Total:" "[email protected]" | 
awk -F: '{sum += $2} 
     END { print sum }' 

Взятым еще дальше, вся работа может быть сделана awk:

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

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

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

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

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

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

HTH!

Смежные вопросы