Расширение фигурных скобок в «обратном порядке»

Usando GNUfind:

find. -type f -mtime +5 \
    -regextype egrep -regex '.*[0-9]{4}-[0-9]{2}-[0-9]{2}[^/]*$' \
    -delete

La expresión regular coincidirá con cualquier cadena en el nombre base de un nombre de ruta que contenga una fecha en el formulario YYYY-MM-DD. Tenga en cuenta que también podemos hacer coincidir XXYYYY-MM-DDZZdonde XXy ZZson ​​algunos otros caracteres.

El [^/]*$al final asegura que en realidad estamos haciendo coincidir la expresión con el nombre base de la ruta actual, y significa "no /para el resto de la cadena, por favor".

Usar un patrón comodín de shell en su lugar (más fácil de mantener):

find. -type f -mtime +5 \
    -name '*[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9]*' \
    -delete

Tenga en cuenta que -mtime +5es para archivos cuya antigüedad como número entero de días es estrictamente mayor que 5, es decir, 6 días o más. Para archivos de 5 días o más, necesitaría -mtime +4.

21
20.06.2019, 21:01
8 ответов
{a..c}1 {a..c}2 {a..c}3

Раскрытие фигурных скобок в {a..c}{1..3}разворачивается слева направо, поэтому сначала вы получаете a{1..3} b{1..3} c{1..3}, а затем буквы объединяются с числами в a1 a2 a3 b1 b2 b3 c1 c2 c3. Чтобы получить желаемый порядок, вам придется использовать немного более длинное выражение выше.

3
27.01.2020, 19:43

Вы могли бы сделать:

$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3

Что затем указывает оболочке оценить:

echo {a..c}1 {a..c}2 {a..c}3
31
27.01.2020, 19:43

Использование петли:

for n in {1..3}; do printf '%s\n' {a..c}"$n"; done

Это зациклит ваше первое расширение, а затем дополнит каждый символ вторым.

Если вам нужен вывод всего в одну строку, вы можете удалить\n:

for n in {1..3}; do printf '%s ' {a..c}"$n"; done

Это не даст вам завершающую новую строку, но если вы передаете ее команде или переменной, это не должно быть проблемой.

2
27.01.2020, 19:43

баш, кш, зш

Один лайнер, который работает в (bash, ksh, zsh)(не все оболочки могут выполнять «расширение скобок» в обратном порядке):

$ echo {3..1}{c..a} | rev
a1 b1 c1 a2 b2 c2 a3 b3 c3

Альтернативой использованию eval(, которая по-прежнему предназначена для bash, ksh, zsh и может быть более загадочной ), является:

$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3

Чтобы понять, что происходит, замените evalнаecho:

$ echo echo '{a..c}'{1..3}
echo {a..c}1 {a..c}2 {a..c}3

Команда, выполненная (после расширения eval ), на самом деле echo {a..c}1 {a..c}2 {a..c}3. Который расширяется по мере того, как вы хотите/нужно.

все снаряды

Существует несколько оболочек без «расширения фигурных скобок», поэтому их невозможно использовать для «всех оболочек». Нам нужен цикл (с завершающим пробелом):

$ for i in 1 2 3; do for j in a b c; do printf "%s%s " "$j" "$i"; done; done; echo
a1 b1 c1 a2 b2 c2 a3 b3 c3 

Если вы не должны добавлять пробелы в конце:

s=""
for i in 1 2 3; do
    for j in a b c; do
        printf "%s%s%s" "$s" "$j" "$i"
        s=" "
    done
done
echo

Печать

a1 b1 c1 a2 b2 c2 a3 b3 c3

ЕСЛИ вам нужно сделать это для многих значений, нам нужно использовать что-то похожее на раскрытие фигурной скобки для создания списка чисел $(seq 10). А так как seq не может сгенерировать список букв, нам нужно преобразовать в ascii сгенерированные числа:

s=""
for i in $(seq 4); do
    for j in $(seq 5); do
        printf "%s\\$(printf %03o $((96+j)))%s" "$s" "$i"
        s=" "
    done
done
echo

отпечатки:

a1 b1 c1 d1 e1 a2 b2 c2 d2 e2 a3 b3 c3 d3 e3 a4 b4 c4 d4 e4
5
27.01.2020, 19:43

В этом конкретном случае я думаю, что вариант, предложенный Стефаном Шазела , является лучшим.

С другой стороны, при расширении более сложных элементов этот параметр плохо масштабируется. Таким образом, вы можете добиться того же:

$ printf '%s\0' {a..c}{1..3} | sort -zk 1.2,1.2 | tr '\0' ' '

, который возвращает:

a1 b1 c1 a2 b2 c2 a3 b3 c3

Выглядит немного запутанно, но теперь у меня есть огромный контроль над порядком, просто изменив два символа в приведенной выше команде; например:

$ echo {a..b}{1..2}{a..b}{1..2}

это расширится до:

a1a1 a1a2 a1b1 a1b2 a2a1 a2a2 a2b1 a2b2 b1a1 b1a2 b1b1 b1b2 b2a1 b2a2 b2b1 b2b2

Предположим, мне нужны все 1во втором расширении, тогда2:

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.2,1.2 | tr '\0' ' '
a1a1 a1a2 a1b1 a1b2 b1a1 b1a2 b1b1 b1b2 a2a1 a2a2 a2b1 a2b2 b2a1 b2a2 b2b1 b2b2

Предположим, мне нужны все aв третьем расширении, тогдаb:

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.3,1.3 | tr '\0' ' '
a1a1 a1a2 a2a1 a2a2 b1a1 b1a2 b2a1 b2a2 a1b1 a1b2 a2b1 a2b2 b1b1 b1b2 b2b1 b2b2

Предположим, мне нужны все 1в четвертом расширении, тогда2:

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.4,1.4 | tr '\0' ' '
a1a1 a1b1 a2a1 a2b1 b1a1 b1b1 b2a1 b2b1 a1a2 a1b2 a2a2 a2b2 b1a2 b1b2 b2a2 b2b2

Предположим, мне нужны все 1aпосередине, затем 1b, затем 2a, затем2b:

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.2,1.3 | tr '\0' ' '
a1a1 a1a2 b1a1 b1a2 a1b1 a1b2 b1b1 b1b2 a2a1 a2a2 b2a1 b2a2 a2b1 a2b2 b2b1 b2b2

Вы даже можете, так же легко, изменить любой порядок в раскрытии выше, просто добавив rк предыдущей команде; например, последний:

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -rzk 1.2,1.3 | tr '\0' ' '
b2b2 b2b1 a2b2 a2b1 b2a2 b2a1 a2a2 a2a1 b1b2 b1b1 a1b2 a1b1 b1a2 b1a1 a1a2 a1a1

Примечание _1:обычно, если это окончательное расширение будет использоваться в качестве списка аргументов, конечный пробел не является проблемой; но если вы хотите избавиться от него, вы можете добавить к любой из приведенных выше команд, например| sed 's/ $//'; или даже | sed 's/ $/\n/', чтобы заменить этот завершающий пробел наnewline

Примечание _2:В приведенных выше примерах я использовал подмножества двух элементов (, т.е.:{a,b} и {1,2})просто для простоты в доказательстве концепции :можно использовать подмножества любой конечной длины, и соответствующие команды будут сравнимы.

10
27.01.2020, 19:43

Выполнено описанным ниже способом

for i in {1..10}; do for j in {a..c}; do echo $j$i; done; done| perl -pne "s/\n/ /g"

выход

a1 b1 c1 a2 b2 c2 a3 b3 c3 a4 b4 c4 a5 b5 c5 a6 b6 c6 a7 b7 c7 a8 b8 c8 a9 b9 c9 a10 b10 c10
-2
27.01.2020, 19:43

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

Измените порядок раскрытия фигурных скобок, затем поменяйте местами символы:

echo {1..3}{a..c} | sed -E 's/(.)(.)( ?)/\2\1\3/g'
2
27.01.2020, 19:43

Одним из простых способов может быть использование sort (1.2,1.2 означает, что вы берете один символ во второй позиции и заканчиваете в том же месте ).

$ for i in {a..c}{1..3}; do echo $i; done|sort -n -k1.2,1.2
a1
b1
c1
a2
b2
c2
a3
b3
c3

Если вы хотите, чтобы они были в одной строке, вы можете использовать tr вот так:

$ for i in {a..c}{1..3}; do echo $i; done|sort -n -k1.2,1.2|tr '\n' ' '
a1 b1 c1 a2 b2 c2 a3 b3 c3
0
27.01.2020, 19:43

Теги

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