Как я инвертирую для цикла?

Для передачи числового аргумента команде введите аргумент сначала. Например, Escape 3 Левых перемещения 3 оставленные символа. Так тип ESC 3 ESC x compare-windows RET или M-3 M-x compare-windows RET.

Наиболее часто используемые команды для сравнения двух файлов являются теми ediff. Можно вызвать их из меню “Tools> Compare (Ediff)”. Существует названная команда ediff-windows-linewise, хотя обычно Вы сравнивали бы два буфера (ediff-buffers) или два файла (ediff-files) или два изменения под системой управления версиями (ediff-revision).Пресса n и p перейти между различными регионами;пресса ? видеть более доступные команды.

26
22.12.2011, 10:40
8 ответов

Попробуйте это, если Вы не рассматриваете разрывы строки как "броские символы":

ls /var/logs/foo*.log | tac | while read f; do
    bar "$f"
done
7
27.01.2020, 19:40
  • 1
    Существует ли метод, который работает с разрывами строки? (Я знаю, что это редко, но по крайней мере ради изучения я хотел бы знать, возможно ли написать правильный код.) –  user541686 22.12.2011, 07:04
  • 2
    Творческий для использования tac для инвертирования потока, и если Вам нравится избавляться от некоторых нежелательных символов как разрывы строки, можно передать по каналу к TR-d '\n'. –  Johan 22.12.2011, 08:07
  • 3
    Это повреждается, если имена файлов содержат новые строки, обратные косые черты или непечатные символы. См. mywiki.wooledge.org/ParsingLs и Как циклично выполниться по строкам файла? (и связанные потоки). –  Gilles 'SO- stop being evil' 22.12.2011, 10:26
  • 4
    Наиболее проголосовавший ответ повредил переменную f в моей ситуации. Этот ответ, хотя, действует в значительной степени как общедоступная замена для дежурного блюда for строка. –  Serge Stroobandt 07.07.2015, 02:14

В ударе или ksh, помещенном имена файлов в массив, и, выполняют итерации по тому массиву в обратном порядке.

files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
  bar "${files[$i]}"
done

Код выше также работает в zsh если ksh_arrays опция установлена (это находится в ksh режиме эмуляции). В zsh существует более простой метод, который должен инвертировать порядок соответствий через спецификатор шарика:

for f in /var/logs/foo*.log(On); do bar $f; done

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

set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
  eval "f=\${$i}"
  bar "$f"
  i=$((i-1))
done
27
27.01.2020, 19:40
  • 1
    После того как Вы используете позиционные параметры, нет никакой потребности в Ваших переменных i и f; просто выполните a shift, использовать $1 для Вашего вызова к bar, и тест на [ -z $1 ] в Вашем while. –  user1404316 15.02.2018, 20:22
  • 2
    @user1404316 Это было бы чрезмерно сложным способом выполнить итерации по элементам в порядке возрастания. Кроме того, неправильно: ни один [ -z $1 ] ни [ -z "$1" ] полезные тесты (что, если параметр был *, или пустая строка?). И в любом случае они не помогают здесь: вопрос состоит в том, как циклично выполниться в противоположном порядке. –  Gilles 'SO- stop being evil' 15.02.2018, 20:38
  • 3
    Вопрос конкретно говорит, что выполняет итерации по именам файлов в/var/log, таким образом, безопасно предположить, что ни один из параметров не был бы "*" или пуст. Я действительно признаю ошибку, тем не менее, на точке обратного порядка. –  user1404316 15.02.2018, 20:42
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar

Должен управлять способом, которым Вы хотите (это было протестировано на Mac OS X, и у меня есть протест ниже...).

Из страницы справочника для находки:

-print0
         This primary always evaluates to true.  It prints the pathname of the current file to standard output, followed by an ASCII NUL character (charac-
         ter code 0).

В основном Вы находите файлы, которые соответствуют Вашей строке + шарик и завершающий каждого с символом NUL. Если Ваши имена файлов содержат новые строки или другие странные символы, находка должна обработать это хорошо.

tail -r

берет стандартный вход через канал и инвертирует его (отметьте это tail -r печать весь вход к stdout и не только последние 10 строк, который является стандартным значением по умолчанию. man tail для большего количества информации).

Мы затем передаем это по каналу к xargs -0 :

-0      Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines.  This is expected to be used in concert with the
         -print0 function in find(1).

Здесь, xargs ожидает видеть аргументы, разделенные символом NUL, от которого Вы передали find и инвертированный с tail.

Мой протест: я считал это tail не играет хорошо с завершенными пустым указателем строками. Это работало хорошо над Mac OS X, но я не могу гарантировать, что это имеет место для всех *, отклоняет. Действовать осторожно.

Я должен также упомянуть, что Параллель GNU часто используется в качестве xargs альтернатива. Можно проверить это, также.

Я могу пропускать что-то, таким образом, другие должны вмешаться.

1
27.01.2020, 19:40
  • 1
    +1 большой ответ. Кажется, что Ubuntu не поддерживает tail -r хотя... я делающий что-то не так? –  user541686 22.12.2011, 08:02
  • 2
    Нет, я не думаю, что Вы. У меня нет своей машины Linux, но быстрый Google для 'человека хвоста Linux' не показывает ее опцией. sunaku упоминается tac как альтернатива, таким образом, я попробовал бы это, вместо этого –  tcdyl 22.12.2011, 08:17
  • 3
    я также отредактировал ответ для включения другого альтернативного –  tcdyl 22.12.2011, 09:01
  • 4
    кричит, я забыл к +1, когда я сказал +1 :( Сделанный! Извините за это ха-ха :) –  user541686 22.12.2011, 09:22
  • 5
    tail -r характерно для OSX и инвертирует разграниченный новой строкой вход, не разграниченный пустым указателем вход. Ваше второе решение не работает вообще (Вы передаете вход по каналу к ls, который не заботится); существует не легкая фиксация, которая заставила бы его работать надежно. –  Gilles 'SO- stop being evil' 22.12.2011, 10:31

Попробуйте это:

for f in /var/logs/foo*.log; do
bar "$f"
done

Я думаю, что это - самый простой путь.

-4
27.01.2020, 19:40
  • 1
    Вопрос, который задают для “for цикл в обратном порядке”. –  manatwork 09.10.2013, 10:52

Если кто-то пытается выяснить, как выполнить обратную итерацию по списку строк, разделенных пробелами, это работает:

reverse() {
  tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}

list="a bb ccc"

for i in `reverse $list`; do
  echo "$i"
done
> ccc
> bb 
> a
3
27.01.2020, 19:40

En su ejemplo, está recorriendo varios archivos, pero encontré esta pregunta debido a su título más general que también podría cubrir el bucle sobre una matriz o la inversión en función de cualquier número de órdenes.

He aquí cómo hacerlo en Zsh:

Si está recorriendo los elementos de una matriz, use esta sintaxis(fuente)

for f in ${(Oa)your_array}; do
   ...
done

Oinvierte el orden especificado en la siguiente bandera; aes el orden de matriz normal.

Como dijo @Gilles, Oninvertirá el orden de sus archivos globbed, p. con my/file/glob/*(On).Eso es porque Ones "orden inverso nombre ".

Indicadores de clasificación Zsh:

  • aorden de matriz
  • Llongitud del archivo
  • lnúmero de enlaces
  • mfecha de modificación
  • nnombre
  • ^oorden inverso(oes orden normal)
  • Oorden inverso

Para ver ejemplos, consultehttps://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txtyhttp://reasoniamhere.com/2014/01/11/outrageously-useful-tips-to-master-your-z-shell/

2
27.01.2020, 19:40

Mac OSX не поддерживает команду tac. Решение @tcdyl работает, когда вы вызываете одну команду в цикле for. Во всех остальных случаях проще всего это обойти следующим образом.

Этот подход не поддерживает символы новой строки в именах файлов. Основная причина в том, что tail -rсортирует входные данные как разделенные символами новой строки.

for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done

Однако есть способ обойти ограничение новой строки.Если вы знаете, что ваши имена файлов не содержат определенного символа (, скажем, '=' ), вы можете использовать tr, чтобы заменить все символы новой строки на этот символ, а затем выполнить сортировку. Результат будет выглядеть следующим образом:

for i in `find [directory] -name '[filename]' -print0 | tr '\n' '=' | tr '\0' '\n'
| tail -r | tr '\n' '\0' | tr '=' '\n' | xargs -0`; do [commands]; done

Примечание. :в зависимости от вашей версии trон может не поддерживать '\0'в качестве символа. Обычно это можно обойти, изменив локаль на C (, но я не помню, как именно, так как после исправления она теперь работает на моем компьютере ). Если вы получили сообщение об ошибке и не можете найти обходной путь, опубликуйте его в комментарии, чтобы я мог помочь вам устранить неполадку.

0
27.01.2020, 19:40

простой способ — использовать ls -r, как упоминал @David Schwartz

for f in $(ls -r /var/logs/foo*.log); do
    bar "$f"
done
-1
27.01.2020, 19:40

Теги

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