Помилка синтаксису біля несподіваного маркера "else"


2

Я намагаюся створити скрипт, який видалить певні частини файлу txt, наповнені інформацією про стан та іншим різним текстом. Я не можу закінчити головне, якщо твердження. Також я намагаюся змусити його видалити найстарішу інформацію про стан, ввівши команду date в скрипт, який генерує output.txt. Чи є спосіб змусити його видалити найдавнішу інформацію. Я в основному намагаюся завершити операцію if. Дякую. (Також спочатку у мене було інше, якщо як у Еліфа, але я отримав ті самі результати.)

./count.sh: рядок 30: помилка синтаксису поблизу несподіваного маркера. else' ./count.sh: line 30:'

WCOUNT=$(wc -l output.txt $1 | awk '{print $1}')

if [[ $WCOUNT -gt 50 ]]; then 

    if [[ "grep CLIENTSTART output.txt" != null ]]; then
        echo $WCOUNT
        sed -i '/\*\*\*CLIENTSTART/,/CLIENTEND\*\*\*/ d' output.txt
        echo $WCOUNT

    else if [[ -n "grep DHCPSTART output.txt" ]]; then          

        echo $WCOUNT
        sed -i '/\*\*\*DHCPSTART/,/DHCPEND\*\*\*/ d' output.txt     
        echo $WCOUNT

    else if [[ -n "grep DNSSTART output.txt" ]]; then
        echo $WCOUNT
        sed -i '/\*\*\*DNSSTART/,/DNSEND\*\*\*/ d' output.txt
        echo $WCOUNT

    else if [[ -n "grep WEBSTART output.txt" ]]; then
        echo $WCOUNT
        sed -i '/\*\*\*WEBSTART/,/WEBEND\*\*\*/ d' output.txt
        echo $WCOUNT

    else
        echo "Cannot help you"
    fi

else
    echo "You're good, homie.  It's under 500"

fi

1
Якщо встановлено $ 1 (перший аргумент командного рядка) і є ім'ям файлу, ваш wc|awkконвеєр фактично виводить три числа, які використовуються як значення WCOUNT; це справді те, що ти хочеш? Якщо ви хочете тільки кількість рядків в одному файлі, вам не потрібно AWK, тільки перепризначення: WCOUNT=$(wc -l <output.txt). Також ваші if [[ "grep something output.txt" ]]тести насправді не розглядають вміст файлу output.txt; після виправлення вкладених файлів, як відповіли, усі тести будуть / завжди будуть успішними незалежно від вмісту файлу.
dave_thompson_085

"Спочатку у мене було інше, якщо як elif's, але я отримав ті ж результати" - зміна їх на elif, як у відповіді Метта повинно запобігти unexpected token elseпомилці. Якщо ви все ще бачите це повідомлення, чи можете ви показати нам elifверсію вашого сценарію, яка його виробляє?
JigglyNaga

Відповіді:


7

Проблема тут полягає в тому, що, використовуючи, else ifа не elif, ви додаєте вкладку в свою програму, і вам потрібно буде додати більше fiоператорів, щоб скасувати додаткові умовні оператори.

Ось відредагована версія вашої програми з дещо іншим відступом, щоб продемонструвати, що я маю на увазі

WCOUNT=$(wc -l output.txt $1 | awk '{print $1}')

if [[ $WCOUNT -gt 50 ]]; then 
    if [[ "grep CLIENTSTART output.txt" != null ]]; then
        echo $WCOUNT
        sed -i '/\*\*\*CLIENTSTART/,/CLIENTEND\*\*\*/ d' output.txt
        echo $WCOUNT
    else 
        if [[ -n "grep DHCPSTART output.txt" ]]; then          
            echo $WCOUNT
            sed -i '/\*\*\*DHCPSTART/,/DHCPEND\*\*\*/ d' output.txt     
            echo $WCOUNT
        else 
            if [[ -n "grep DNSSTART output.txt" ]]; then
                echo $WCOUNT
                sed -i '/\*\*\*DNSSTART/,/DNSEND\*\*\*/ d' output.txt
                echo $WCOUNT
            else 
                if [[ -n "grep WEBSTART output.txt" ]]; then
                    echo $WCOUNT
                    sed -i '/\*\*\*WEBSTART/,/WEBEND\*\*\*/ d' output.txt
                    echo $WCOUNT
                else
                    echo "Cannot help you"
                fi
            fi
        fi
    fi
else
    echo "You're good, homie.  It's under 500"

fi

Крім того, ви можете просто використовувати elif

WCOUNT=$(wc -l output.txt $1 | awk '{print $1}')

if [[ $WCOUNT -gt 50 ]]; then 

    if [[ "grep CLIENTSTART output.txt" != null ]]; then
        echo $WCOUNT
        sed -i '/\*\*\*CLIENTSTART/,/CLIENTEND\*\*\*/ d' output.txt
        echo $WCOUNT

    elif [[ -n "grep DHCPSTART output.txt" ]]; then          

        echo $WCOUNT
        sed -i '/\*\*\*DHCPSTART/,/DHCPEND\*\*\*/ d' output.txt     
        echo $WCOUNT

    elif [[ -n "grep DNSSTART output.txt" ]]; then
        echo $WCOUNT
        sed -i '/\*\*\*DNSSTART/,/DNSEND\*\*\*/ d' output.txt
        echo $WCOUNT

    elif [[ -n "grep WEBSTART output.txt" ]]; then
        echo $WCOUNT
        sed -i '/\*\*\*WEBSTART/,/WEBEND\*\*\*/ d' output.txt
        echo $WCOUNT

    else
        echo "Cannot help you"
    fi

else
    echo "You're good, homie.  It's under 500"

fi

(Крім того, незначна нитка, ви перевіряєте, чи є більше 50 рядків, але ваше вихідне повідомлення вказує на те, що ви перевіряєте на 500. Хоча технічно є 500 рядків, це трохи оману: p)

EDIT: Як уже зазначали інші, це виправить вашу синтаксичну помилку, але все ж є інші проблеми зі сценарієм. Я рекомендую також прочитати їх коментарі / відповіді.


Відповідь не стосується того факту, який -n "grep ..."слід перевірити (дивним завжди, оскільки рядок grep ...не порожній).
Кусалаланда

Хочете забрати [[ "grep CLIENTSTART output.txt" != null ]]і своїх однаково поламаних аналогів?
roaima

1

Причина, по якій ви отримуєте синтаксичну помилку, полягає в тому, що ваші else ifзаяви повинні бути elif.

Якщо ви дасте wc -lдва файли, це дасть три рядки виводу:

$ wc -l .profile .profile
      30 .profile
      30 .profile
      60 total

Це впливає на найперший ifтест, де $WCOUNTвін не цитується, і його розширення вводить ще одну синтаксичну помилку.

Ви, мабуть, хочете

WCOUNT=$( wc -l <output.txt )

Крім того, у вас є ряд тестів на зразок рядків "grep DHCPSTART output.txt". Ці тести завжди будуть правдивими.

Щоб перевірити наявність рядка у файлі, використовуйте

if grep -Fq 'fixed string' filename; then

напр

if grep -Fq 'CLIENTSTART' output.txt; then
   # do something
elif grep -Fq 'DHCPSTART' output.txt; then
   # do something
else
   # do something
fi

На -qзупинках grepвід виробництва якої - або фактичної потужності. Її статус виходу визначає, знайдено рядок чи ні, і саме це робить ifоператор спрацьованим (прапор також змушує grepзупинити читання файлу при першому збігу). -FПрапора робить grepставитися до заданим шаблоном у вигляді фіксованої рядки , а не як регулярний вираз.


Пропозиція щодо внутрішнього сценарію:

tmpfile=$(mktemp)

for string in CLIENT DHCP DNS WEB; do
    if grep -Fq "${string}START" output.txt; then
        sed "/\*\*\*${string}START/,/${string}END\*\*\*/d" \
            output.txt >"$tmpfile"
        break
    fi
done

if [ -s "$tmpfile" ]; then
    mv "$tmpfile" output.txt
else
    echo 'Can not help you'
    rm -f "$tmpfile"
fi

[ -s "$tmpfile" ]Тест буде успішним , якщо файл $tmpfileмає розмір більше нуля (що буде , якщо sedбув викликаний).

forПетля з breakнаслідує вашу if ... then ... elifлогіку , але в більш компактному вигляді.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.