Как я хочу петить, если оператор в Bash?

С awk:

awk -F"\t" '$1!=""&&$2!=""&&$3!=""' file

На самом деле все просто.

  • awk разделяет ввод на табуляции разделителя полей \t, заданного флагом -F. Этот флаг может быть опущен, если в вашем контенте нет пробелов в полях.
  • $1!=""&&... - это условие. Когда это условие истинно, awk просто печатает строку. Вы также можете написать '$1!=""&&$2!=""&&$3!=""{print}', но это не обязательно. Поведение Awks по умолчанию заключается в печати строки, если не задано никакого действия. Здесь это условие верно, когда поля $1, $2 и $3 не пусты, следовательно, когда первые три поля имеют значение.

Для записи в другой файл используйте следующее:

awk -F"\t" '$1!=""&&$2!=""&&$3!=""' input_file >output_file

Edit: awk, он проверяет каждое поле в строке:

awk -F"\t" '{for(i=1;i<=NF;i++){if($i==""){next}}}1' file
1
04.02.2019, 14:52
3 ответа

У вас есть синтаксические и логические ошибки.

$a=true— это просто строка, а НЕ операция сравнения. Разделяйте пробелами, чтобы происходило сравнение:"$a" = true.

При такой работе петля вообще не будет введена, так как вы установили a=falseзаранее.

ЕСЛИ вы, наконец, войдете в цикл, вы не сможете выйти, так как aникогда не устанавливается ни на что, кроме true, и не используется другой механизм выхода (, например.break)предусмотрено.

2
27.01.2020, 23:23

Попробуйте использовать просто break, чтобы остановить бесконечный цикл, подобный этому:

echo "$(tput setaf 4)  Tell me where the file is:"
echo # This prints empty line like printf "\n"

while true; do # 'while true' or 'while :' is infinite loop
    read i
    if [ -r $i ]    # You probably mean -r (readable) and not -w (writable)
    then
        cat $i | grep stuff > i2
        break # 'break' ends loop
    else
        echo -n "Oh something is wrong, try again!" # 'echo -n' means print without newline character
        sleep 3
    fi
done

Измененные места имеют комментарии с описанием.

0
27.01.2020, 23:23

Как указывали другие, в вашем коде есть логические и синтаксические ошибки. Сайт ShellCheck хорош для отсеивания синтаксических ошибок.

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

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

#!/bin/sh

pathname=$1

if ! grep 'pattern' <$pathname >i2; then
    echo 'Something is wrong' >&2
fi

Описанный выше echoбудет выполнен, когда

  • файл в $pathnameне может быть прочитан или
  • файл i2не может быть записан или
  • шаблон не был найден в$pathname(это отличается от вашего кода, но см. ниже ).

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

С интерактивной подсказкой и задержкой:

#!/bin/bash

while true; do
    read -r -p 'Pathname: ' pathname

    if grep 'pattern' <$pathname >i2; then
       break
    fi

    echo 'Something is wrong' >&2
    sleep 3
done

Здесь у нас есть бесконечный цикл, который считывается от пользователя и выходит из цикла, если вызов grepпрошел нормально. Если grepне удалось по какой-либо причине (одной из трех причин, указанных выше ), имя пути запрашивается снова.


Оба фрагмента кода с отдельным тестом для читаемого файла (grepдопускают сбой, поскольку ничего не находят или не могут записать в свой выходной файл.

Первая не -интерактивная версия:

#!/bin/sh

pathname=$1

if [ ! -r "$pathname" ]; then
    echo 'Something is wrong' >&2
fi

grep 'pattern' <$pathname >i2

Затем интерактивная версия:

#!/bin/bash

while true; do
    read -r -p 'Pathname: ' pathname

    if [ -r "$pathname" ]; then
       grep 'pattern' <$pathname >i2
       break
    fi

    echo 'Something is wrong' >&2
    sleep 3
done

Или,интерактивная версия, в которой цикл имеет дело только с пользовательским вводом и проверкой:

#!/bin/bash

while true; do
    read -r -p 'Pathname: ' pathname

    [ -r "$pathname" ] && break

    echo 'Something is wrong' >&2
    sleep 3
done

grep 'pattern' <$pathname >i2
1
27.01.2020, 23:23

Теги

Похожие вопросы