Программирование Shell, избегая tempfiles

Это зависит от точной функциональности find то, что Вы полагаетесь. Если это - (преимущественно) функциональность открытия, некоторые оболочки поддерживают рекурсивные шарики. Например, с zsh:

% find . -name \*c
./a/b/foo.c
./a/bar.c
./baz.c
inoshiro% ls *.c
baz.c
% ls **/*.c 
a/bar.c  a/b/foo.c  baz.c

Zsh имеет намного больше подобных находке возможностей через спецификаторы шарика (взгляд около конца man zshexpn). Например:

ls -l **/*(.)  ≈  find -type f -ls
ls *(m-2u:$USER:)  ≈  find -mtime -2 -user $USER

Bash 4 также имеет **/ (необходимо включить его с shopt -s globstar), но ничто как спецификаторы шарика.

8
28.09.2011, 15:10
4 ответа

Ваш код похож на полностью выровненный по ширине пример использования tempfiles мне. Я остался бы: палка с этим подходом. Единственной вещью, которая действительно должна быть изменена, является способ, которым Вы создаете tempfile. Используйте что-то как

 TMP=$(tempfile)

или

 TMP=$(mktemp)

или по крайней мере

 TMP=/tmp/myscript_$$

Таким образом, Вы не будете позволять имени быть легко предсказанным (безопасность) и управлять интерференцией между несколькими экземплярами сценария, работающего одновременно.

9
27.01.2020, 20:09
  • 1
    педантично, кавычки не требуются для переменного присвоения. –  glenn jackman 28.09.2011, 16:00
  • 2
    @glenn Правда, в этом случае они не должны иметь значения, так как каждая из команд обычно производит строку без пробелов. Но это - хорошая привычка иметь кавычки в случаях, где Вы присваиваете вывод команды переменной - таким образом, я сохраню при отъезде его этот путь. –  rozcietrzewiacz 29.09.2011, 09:36
  • 3
    Удаленный кавычки в последнем примере для различия. –  rozcietrzewiacz 29.09.2011, 09:40
  • 4
    @roz нет, Вы упустили суть. Переменные присвоения в оболочке распознаны, прежде чем любые расширения сделаны, и полевое разделение НЕ сделано для переменных присвоений. Таким образом, var=$(echo lots of spaces); echo "$var" прекрасен и должен произвести lots of spaces как произведено. Реальный протест, который никто не упомянул, является полосами замены команды все запаздывающие новые строки. Это не проблема здесь и только имеет значение, например, если у Вас был поврежденный mktemp это создало имена файлов с запаздывающими новыми строками. Обычная работа вокруг при необходимости var=$(echo command with trailing newline; echo x); var=${var%x}. –  jw013 24.08.2012, 16:42
  • 5
    @jw013 Да, я понимаю, что это теперь - не сделало, когда я записал ответу год назад. Спасибо за указание на него! (фиксирующий...) –  rozcietrzewiacz 24.08.2012, 18:13

Вы могли использовать переменную:

info="$(getInfo $SERVICE)"
SERV_NAME="$(head -1 $TMPFILE <<<"$info" | sed -e 's/ $//')"
...

От man ksh:

<<<word       A  short  form of here document in which word becomes the
              contents of the here-document after any parameter  expan-
              sion,  command  substitution, and arithmetic substitution
              occur.

Преимущества включают:

  • Включает параллельное выполнение.
  • По моему опыту, это - тонны быстрее, чем временные файлы. Если у Вас нет такого большого количества данных, что Вы заканчиваете тем, что подкачали их, должны быть порядки величины быстрее (только запрещающий буферы кэширования HD, которые могли бы быть почти столь же быстрыми для небольших сумм данных).
  • Другие процессы или пользователи не могут испортить Ваши данные.
5
27.01.2020, 20:09
  • 1
    <<<, кажется, не существует в моем ksh. Я получаю ошибку, и я, может казаться, не нахожу его в странице справочника. Я использую ksh88. Вы уверены, что эта версия должна иметь эту функцию? –  rahmu 28.09.2011, 16:23
  • 2
    Нет; я предполагаю, что не проверял право man страница (не было никакого упоминания о номере версии на веб-странице:/) –  l0b0 28.09.2011, 16:45
  • 3
    <<< удар, 'здесь представляют в виде строки'. Я не думаю, что это появляется в любой другой оболочке. (О, zsh возможно...) –  rozcietrzewiacz 29.09.2011, 09:31
  • 4
    @rozcietrzewiacz: Google для man ksh. Это было, конечно, упомянуто там. –  l0b0 29.09.2011, 11:06
  • 5
    Угадайте, как удар реализует здесь-строки и здесь-документы. sleep 3 <<<"here string" & lsof -p $! | grep 0rsleep 30251 anthony 0r REG 253,0 12 263271 /tmp/sh-thd-7256597168 (deleted) — да, это использует tempfile. –  derobert 24.08.2012, 20:04

У Вас есть две опции:

  1. Вы получаете данные однажды (в Вашем примере с getInfo) и сохраните его в файле, как Вы делаете.

  2. Вы выбираете данные по каждому разу и не храните их локально, т.е. Вы звоните getInfo каждый раз

Я не вижу проблемы в создании временного файла для предотвращения reprocessing/re-fetching.

Если Вы волнуетесь по поводу отъезда временного файла где-нибудь, можно всегда использовать trap убеждаться удалить его в случае, если сценарий уничтожается/прерывается

trap "rm -f $TMPFILE" EXIT HUP INT QUIT TERM

и используйте mktemp создать уникальное имя файла для Вашего временного файла.

2
27.01.2020, 20:09

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

for SERVICE in $(myfunc); do
    eval $(getInfo $SERVICE |
               sed -n -e '1/\(.*\) *$/SERV_NAME="\1"/p' \
                   -e '/HOSTNAME/s/^[^=]*=\([^=]*\).*/SERV_HOSTNAME="\1"/p' \
                   -e '/Arguments/^[^:]*:\([^:]*\).*/SERV_ARGS="\1"/p')
    print $SERV_NAME $SEP $SERV_HOSTNAME $SED $SERV_ARGS
done

Или если Вы просто хотите распечатать информацию:

for SERVICE in $(myfunc); do
    getInfo $SERVICE | awk -vsep="$SEP" '
        BEGIN{OFS=sep}
        NR == 1 { sub(/ *$/,""); SERV_NAME=$0 }
        /HOSTNAME/ { split($0, HOST, /=/; SERV_HOSTNAME=HOST[2]; }
        /Arguments/ { split($0, ARGS, /:/; SERV_ARGS }
        END { print SERV_NAME, SERV_HOSTNAME, SERV_ARGS }'
done
1
27.01.2020, 20:09

Теги

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