Bash во время чтения строки не печатает каждую строку в условии - PullRequest
3 голосов
/ 10 марта 2019

У меня следующая ситуация:

У меня есть текстовый файл, который я пытаюсь зациклить, чтобы я мог знать, имеет ли каждая строка совпадение с «.mp3» в данном случае, а именно:

12 Stones.mp3
randomfile.txt
Aclarion.mp3
ransomwebpage.html
Agents Of The Sun.mp3
randomvideo.mp4

Итак, я написал следующий скрипт для его обработки:

while read line || [ -n "$line" ]
do
varline=$(awk '/.mp3/{print "yes";next}{print "no"}')
echo $varline
if [ "$varline" == "yes" ]; then
        some-command
    else
         some-command
    fi
done < file.txt

Ожидаемый результат будет:

yes
no
yes
no
yes
no

Вместо этого, кажется, пропускаетпервая строка и я получаю следующее:

no
yes
no
yes
no

Ответы [ 3 ]

4 голосов
/ 10 марта 2019

Вам действительно не нужен Awk для простого сопоставления с образцом, если это все, для чего вы его использовали.

while IFS= read -r line; do
    case $line in
     *.mp3) some-command;,
     *) some-other-command;;
    esac
done <file.txt

Если вы в любом случае используете Awk по другим причинам, зацикливание строк в цикле оболочки неэффективно и очень часто является антипаттерном. Это на самом деле не исправляет это, но по крайней мере позволяет избежать запуска нового экземпляра Awk на каждой итерации:

awk '{ print ($0 ~ /\.mp3$/) ? "yes" : no" }' file.txt |
while IFS= read -r whether; do
    case $whether in
     'yes') some-command ;;
     'no') some-other-command;;
    esac
done

Если вам также нужно содержимое "$line", то распечатка его из Awk и чтение двух различных переменных - тривиальное изменение.

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

2 голосов
/ 10 марта 2019

Ты что-то забыл?Ваш awk не имеет явного ввода, замените его следующим образом:

while IFS= read -r read line || [ -n "$line" ]
do
varline=$(echo "$line" | awk '/.mp3/{print "yes";next}{print "no"}')
echo $varline
if [ "$varline" == "yes" ]; then
        some-command
    else
        some-other-command
    fi
done < file.txt

В этом случае вам может потребоваться изменить значение на /\.mp3$/ или /\.mp3[[:space:]]*$/ для точного соответствия.
Потому что . будет соответствовать любому символу, например, /.mp3/ также будет соответствовать Exmp3but.mp4.
Обновление: изменено while read line на while IFS= read -r read line, чтобы сохранить содержимое каждой строки без изменений при назначении переменной.

И часть awk может быть улучшена до:

awk '{print $0~/\.mp3$/ ? "yes":"no"}'

Так что только с awk вы можете сделать это так:

awk '{print $0~/\.mp3$/ ? "yes":"no"}' file.txt

Или если ваша цель простоКоманды в структуре if, вы можете просто сделать это:

awk '/\.mp3$/{system("some-command");next}{system("some-other-command");}' file.txt

или это:

awk '{system($0~/\.mp3$/ ? "some-command" : "some-other-command")}' file.txt
2 голосов
/ 10 марта 2019

Использование awk

$ awk '{if ($0 ~ /mp3/) {print "yes"} else {print "no"}}' file.txt
yes
no
yes
no
yes
no

Или более кратко:

$ awk '/mp3/{print "yes";next}{print "no"}' file.txt
$ awk '{print (/mp3/ ? "yes" : "no")}' file.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...