Сортировка петли в оболочке - PullRequest
1 голос
/ 22 декабря 2011

у меня нормальный ...

for file in *
do
    #do something here
done

... Код. Проблема в том, что я хочу отсортировать строку файлов по пользовательской дате, дата определяется во второй строке файлов. У меня тут проблемы:

1.Как узнать, что находится во второй строке этих нескольких файлов, прежде чем я на самом деле запустите

for file in * do

2. Как мне тогда отсортировать цикл по этой пользовательской строке?

Это не работает, но, возможно, это поможет вам понять мою проблему:

for file in *
do
    customdate="$(sed -n 2p $file)"
done

for file in * sort by $customdate
do
    #do something here
done

Ответы [ 3 ]

0 голосов
/ 22 декабря 2011

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

index=""
for file in *
do
   customdate="$(head -2 $file | tail -1)"
   index="${index}${customdate},${file}\n"
done

for key in `echo -e ${index} | sort`
do
   customdate=${key/,.*/}
   file=${key/.*,/}
   # PROCESS FILE HERE
done
0 голосов
/ 23 декабря 2011

Начиная с zsh 4.3.9dev2, существует специальный классификатор для пользовательской сортировки:

oe и o+ являются особыми случаями;за каждым из них следует шелл-код, разделенный как для квалификатора glob e и квалификатора glob + соответственно (см. выше).Код выполняется для каждого сопоставленного файла с параметром REPLY, установленным на имя файла в записи, и globsort, добавленным к zsh_eval_context.Код должен каким-то образом изменить параметр REPLY.По возвращении значение параметра используется вместо имени файла в качестве строки для сортировки.

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

for file in *(oe\''REPLY=$({ read -r REPLY && IFS= read -r REPLY; } <$REPLY)'\'); do …

Если ваша дата состоит только из части строки или имеет какой-то странный формат, проанализируйте ее.Например, если у вас есть дата в европейском стиле (день / месяц / год):

for file in *(oe\''REPLY=$({ read -r REPLY && IFS=/ read -r d m y &&
                             REPLY=$((y*10000+m*100+d)); } <$REPLY)'\'); do …

В любой оболочке вы можете создать список имен с добавленной датой, отсортировать этот список, а затем вырезатьвне даты.Я предполагаю, что ни одно из имен файлов не содержит символа новой строки, и ни одна из дат не содержит символов |.

names=
IFS='
'
for file in *; do
  { read -r line; read -r line; } <"$file"
  # If needed, process $line into something that is to be sorted lexicographically.
  names="$names
  $line|$file"
done
names=$(echo "$names" | sort)
set -f
for file in $names; do
  set +f
  file=${file#*|}
  …
done
0 голосов
/ 22 декабря 2011

Вы должны просто сделать две петли вместе, что-то вроде этого:

for file in *
do
  customdate = "$(head -2 $file | tail -1)"
  # do something here, e.g. pipe to sorting command, call sorting function, or whatever
done

Это читает пользовательскую дату из файла, как вы делали (просто используя немного другие команды, в основном потому, что я сосу на sed). Намерение состоит в том, что у вас есть $customdate, доступный в то же время, что и $file содержит правильное имя, поэтому вы можете использовать оба в сортировке.

...