Pull to refresh

Comments 30

одни люди борются с башизмами, другие пишут о них статьи

UFO landed and left these words here
мифическую совместимость непонятно с чем

из 6 систем с linux у меня на столе bash есть на 2 (на 3 из 7, если считать android за linux-систему).
за freebsd не слежу, там уже появился bash в дефолтной установке?


с кучей лишних действий и абсолютно нечитаемыми конструкциями

можно подумать, что массивы bash — верх читаемости.


и что, кроме классического bourne shell и bash больше скриптовых языков нет?
ИМХО если потребовались массивы, то это уже повод задуматься о другом языке программирования.


P. S. я не говорю, что башизмы — вселенское зло и их никогда нельзя использовать; это как goto и глобальные переменные — иногда делают жизнь лучше, но в целом нужно стремиться избегать.

UFO landed and left these words here
удачи вам с обработкой сотни тысяч строк в каком-нибудь однострочнике, который надо написать за пару минут.


Например? Где необходим массив, там будет его заполнение и какая-то обработка (как минимум 2 конструкции, похожие на цикл). Однострочник такого размера выглядит достаточно неприятно (для меня), чтобы решать эту задачу другим способом.
UFO landed and left these words here
Больше писать, но выполнение за 10 сек, выигрыш в 4 раза.
Хм, есть же вариант, когда и меньше писать, на один символ, и без всяких этих ваших «башизмов», чистый POSIX.
while read -r line; do
    echo "$line changed"
done < /tmp/1m_lines.txt > /tmp/output-out.txt

Общее время: 0m17.949s против 1m46.314s, 6 раз. Кстати, хотя общее время этого варианта такое же, как у башизнутого варианта, но по процессорному времени, POSIX вариант в 1,24 раза быстрее башизнутого.
UFO landed and left these words here
Во-первых, эти варианты при практическом использовании не равнозначны


Равнозначны. Медленный вариант 1 000 000 раз открывает/закрывает файловый дескриптор — вот и весь секрет медленности.

Во-вторых, массивы это не просто красивая обертка для чтения кучи строк


Не возражаю. Я и раньше знал, что массивы в bash есть, но зачем они там нужны — неизвестно. Просто как только у меня возникает задача, в которой нужно что-то делать с массивами — желание сделать это в bash сразу пропадает;) На десктопе — есть oocalc и python, там всё это значительно легче.
UFO landed and left these words here
Не смог повторить ситуацию, когда баш вариант сожрал больше процессора, в обоих случаях плюс-минус одно и то же, POSIX вариант незначительно медленнее.
Я Вас умоляю! Очевидно ж, это ж зависит от длины строк. Для понимания, что массивы bash это только синтаксический сахар и ничего больше, в деле «башизмов» можете опробовать следующий код:
readarray -t lines < /tmp/1m_lines.txt
printf "%s changed\n" "${lines[@]}" > /tmp/output-bash1.txt
Который в 2...3 раза короче и шустрее вашего, поскольку не имеет хотя бы цикла.

А заодно, и подумать над вопросом: «Почему нормальные реализации массивов в POSIX awk, а так же в perl или python, входящие в стандарт Linux, выполняют эту же задачу на два порядка быстрее?»
UFO landed and left these words here
Извиняйте, но странный код глаз режет. Да ещё ж и со странным примечанием: «Больше писать, но выполнение за 10 сек, выигрыш в 4 раза.»

Впрочем, задача «дописать в каждую строку файла текст» средствами только shell имеет свой интерес. И похоже башизмы для неё совсем не полезны.
P.S.
Да, забытый POSIX вариант, вероятной самый шустрый из всех чисто shell/bash вариантов:
IFS='
' 
printf "%s changed\n" $(cat /tmp/1m_lines.txt) > /tmp/output-pos.txt
Писали бы лучше про именованные массивы, кому обычные в баше нужны)

Да хотя бы джавистам, которые до сих пор свои JAVA_OPTS собирают конкатенацией строк, вместо того, чтобы пользоваться массивом.

Как бы, даже под macOS/Linux их пугает:
$ man sh
...
       If  bash  is  invoked  with  the name sh, it tries to mimic the startup
       behavior of historical versions of sh as  closely  as  possible,  while
       conforming  to the POSIX standard as well... 
       ... posix mode...

И не говоря уж за Solaris/AIX/FreeBSD/… Говорят, Java многоплатформенная ж…

Это из разряда "ну, бороду я, допустим, сбрею… Но умище, УМИЩЕ то куда деть?.."

Массивы в баше очень полезны, весь piu-piu на них держится)
Небольшой хинт, используя printf, можно обойтись без for циклов:
printf без for
$ arr=(a b c d)
$ printf "%s\n" ${arr[@]}
a
b
c
d

В статье Вы не упомянули о различии в обработке
Упомянули, но одним коротким абзацем без примеров.


  • ${arr[*]}
  • ${arr[@]}
  • "${arr[*]}"
  • "${arr[@]}"

Например:


x=( "hello world" "I am" bash )

# каждое слово в отдельной строке
printf "%s\n" ${x[*]}
printf "%s\n" ${x[@]}

# все слова в одной строке
printf "%s\n" "${x[*]}"

# каждый элемент массива в отдельной строке
printf "%s\n" "${x[@]}"

Дополнение. На самом деле автор упомянул об этом — я не заметил этот абзац в тексте:


Обратите внимание, что символ "@" может быть использован вместо "" в конструкциях типа {arr[]}, результат будет одинаковым за исключением разворачивания записи в кавычках. "$" и "$@" выведут записи в кавычках, "${arr[]}" вернет каждую запись как одно слово, "${arr[@]}" вернет каждую запись в виде отдельных слов.
Вот за что нетривиальные скрипты баш не люблю, ну как такое читать.
${!arr[*]} против например arr.keys()
${!arr[*]} против например arr.keys()


bash vs python?
-пациент, вы курите?
-нет
-пьете?
-нет
-на bash пишиете?
-нет
— ну тогда это очень усложняет диагностику заболевания )))))
И не слова не сказано про именованные(associative) массивы, которые позволяют использовать вместо индексов(0,1,2...) свои произвольные идентификаторы.
Пример associative array
#initialising
declare -A arr
arr[some_string]=test1
arr[some_string2]=test2
arr[1234]=test3
#values out
$ echo ${arr[@]}
test2 test3 test1
#keys out
$ echo ${!arr[@]}
some_string2 1234 some_string

возможно, вы не знакомы с такой полезной особенностью bash как массивы
Извините, но что у Вас с русским языком? Вот не удержался, глаза режет.

Особенность — характерное, отличительное свойство кого-/чего-нибудь.
С каких пор массивы — это «отличительная» черта Bash? Массивы есть во многих языках, и Bash тут совсем не исключение. Их наличие нисколько не делает Bash особенным.

… you may not be familiar with bash's array feature.
В данном контексте «bash's feature» — это, скорее, «часть языка Bash» [1].

[1] dictionary.cambridge.org/ru/словарь/английский/feature
С каких пор массивы — это «отличительная» черта Bash?


По сравнению с sh. Сравнивать bash с любым другим языком вряд ли имеет смысл.
bash по сравнению с чуть более старой версией баш можно сравнить.
В bash ассоциативные массивы появились недавно (по меркам линукса). Но гораздо гораздо раньше они уже активно и удобно использовались в перл, а потом в питон.

Поэтому ладно еще обычные массивы, бывает полезно. Но ассоциативные завезли и хорошо. Нет смысла это особо хайлайтить, потому что любые более-менее сложные задачки лучше писать на других языках.
А баш оставить для стандартной штуки, а именно — удобство и автоматизация работы в CLI, плюс административные штуки и инсталляционные скрипты.
Sign up to leave a comment.

Articles