Intereting Posts
Потяните метаданные из видео в терминале Застрял установку TexLive с нуля на Debian KDE! Написание системного файла systemd с исполняемым путем установки окружения Могу ли я «перетащить» файл в окно без файлового менеджера? Является ли он частью любого стандарта (например, POSIX), что системные файлы должны быть более строчными? Linux замораживает случайно Apache: Имитировать 100 новых подключений в секунду с помощью ab Команда Pipe для хвоста: когда первая команда прервана? как установить модуль в правильном месте или сказать / lib / modules / `uname -r` Разрешение NFS отклонено Symlinked systemd скрипт не запускается при загрузке без daemon-reload Как изменить права доступа / владельца или удалить папку для скачивания (владелец: root wheel)? чашки: время ожидания подключения Ошибка сравнения регулярных выражений Bash для шестнадцатеричного байта \ x01 Почему мой ключ Compose не передается Synergy?

Тестирование, если строка существует внутри массива строк

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

Сейчас это выглядит так:

weekdays=([Mon]=1 [Tue]=1 [Wed]=1 [Thu]=1 [Fri]=1 [Sat]=1 [Sun]=1) input="/Foo/Bar.log" while read -r line do cutline="$(echo ${line} | cut -c 1-3" if [[ ${weekdays["$cutline"]} ]] then echo "Match" else echo "No Match" fi done < ${input} 

Строка получается правильно, но что-то во время теста возвращает false Positive, так как независимо от того, что первые 3 буквы, он возвращает «Match».

Когда я проверил скрипт с -x, он показал мне вместо фактического теста, который он вместо этого использовал

 [[ -n 1 ]] 

И когда я протестировал его с помощью выражения [ ] он показал 1

Проверяет ли он каждый символ в массиве, а не только целые слова, или что-то еще не так с ним?

Если нет проблем, есть ли другой способ сравнить первые три буквы строки со всем, что нужно, массивом, прежде чем продолжить со следующего?

В качестве побочного примечания: я действительно запускаю Bash 4, поэтому ассоциативные массивы должны работать

Основная ошибка заключается в том, что вы фактически не объявляете ассоциативный массив:

 $ weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1) $ echo ${weekdays[@]} 1 $ echo ${weekdays[0]} 1 $ echo ${weekdays[2]} $ 

Я не совсем уверен, как bash справляется с этим, и почему это просто занимает 1 , но я уверен, что это не ассоциативный массив. Как объясняется в man bash (акцент мой):

Индексированный массив создается автоматически, если любой переменной присваивается имя синтаксиса [индекс] = значение. Подстрочный индекс рассматривается как арифметическое выражение, которое должно быть оценено числом. Чтобы явно объявить индексированный массив, используйте declare -a имя (см. SHELL BUILTIN COM-MANDS ниже). declare – имя [нижний индекс] также принимается; подценарий игнорируется.

Ассоциативные массивы создаются с использованием объявления -A name.

Итак, попробуйте это вместо этого, и он будет работать так, как вы ожидаете:

 declare -A weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1) 

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

 #!/bin/bash declare -A weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1) input="/Foo/Bar.log" cut -c 1-3 "$input" | while read -r line; do if [[ ${weekdays["$line"]} ]] then echo "Match : $cutline : ${weekdays[$line]}" else echo "No Match" fi done 

Хотя я, вероятно, сделаю это так:

 #!/bin/bash cut -c 1-3 "$1" | while read -r line; do case $line in "Mon"|"Tue"|"Wed"|"Thu"|"Fri"|"Sat"|"Sun") echo yes;; *) echo no;; esac done 

Затем запустите сценарий с именем целевого файла в качестве аргумента:

 script.sh /Foo/Bar.log" 

Я бы использовал один вызов инструмента обработки текста для обработки текста , а не несколько инструментов для каждой строки ввода:

 awk -v 'weekday=(Mon|Tue|Wed|Thu|Fri|Sat|Sun)' ' {print ($0 ~ "^" weekday ? "" : "No ") "Match"}' < "$input" 

Вы должны использовать цикл, если вам нужно запустить конкретное приложение для каждой строки ввода, но если это просто обработка текста, например вывод строки в какой-либо файл, тогда awk может сделать это так:

 awk -v 'weekday=Mon|Tue|Wed|Thu|Fri|Sat|Sun' ' (day = substr($0, 1, 3)) ~ weekday { print substr($0, 4) > day ".txt" } < "$input"