Найти работу с регулярным выражением в том же CWD, но не из другого каталога

Предположим, что у вас есть строка в переменной lineи вы хотите вывести строку yes, если она не начинается с символа #. В приведенных ниже примерах я также выведу no, если условие не выполняется.

case $line in
    "#"*) echo no
esac

Оператор caseпринимает переменную, а затем любое количество (подстановочных шаблонов )и выполняет код для шаблона, который соответствует значению переменной. В этом случае мы пытаемся сопоставить шаблон"#"*(#, который должен быть заключен в кавычки, чтобы не восприниматься как введение комментария ), и если он соответствует, выполняется оператор echo.

Если шаблонов больше, то код для всех шаблонов, кроме последнего, должен заканчиваться ;;, как в

case $line in
    "#"*) echo no ;;
    *)    echo yes
esac

...и код шаблона может быть пустым:

case $line in
    "#"*) ;;
    *)    echo yes
esac

Оболочка bashтакже выполняет сопоставление шаблонов с шаблонами в [[... ]]с помощью оператора ==:

if [[ $line != "#"* ]]; then
    echo yes
else
    echo no
fi

В bashвы также можете использовать сопоставление регулярных выражений с оператором =~внутри[[... ]]:

if ! [[ $line =~ ^# ]]; then
    echo yes
else
    echo no
fi

или

if [[ $line =~ ^[^#] ]]; then
    echo yes
else
    echo no
fi

Если вы стираете файл построчно, то оболочка не подходит для этой работы. Вместо этого вы можете использовать что-то вродеawk:

awk '/^[^#]/ { print yes }' 

Связанные:

0
29.05.2021, 08:43
1 ответ

-regex(не стандартный ), так как стандартный -pathсоответствует полному пути к файлам. Эти пути начинаются с содержимого $directory, за которым следуют каталоги и файлы, найденные find. Поэтому, если $directoryравно /some/dir, -regexбудет соответствовать регулярному выражению против /some/dir/file-discovered-by-findи никогда не будет соответствовать здесь, поскольку первый символ — это /, а не alnum.

В первом случае ваше регулярное выражение, начинающееся с ^./(, должно было быть ^\./, поскольку .является оператором регулярного выражения, или просто \./, поскольку ^подразумевается в GNU find-regex). ] как $directoryбыл ..

Вам нужно будет сделать что-то подобное с $directory, имея в виду, что все операторы регулярных выражений в$directory(^$*()+[]?.\... )должны быть экранированы. Но и здесь можно:

find "$directory" -maxdepth 1 -type d -regextype posix-extended \
  -regex '.*/[[:alnum:]]+([-_][[:alnum:]]+)*-[[:digit:]]{1,3}(\.[[:digit:]]{1,3}){0,3}'

(Я также заменил .на \., так как я подозреваю, что вы хотите сопоставить литерал ., а не просто любой символ, и удалил ?, который здесь не нужен ).

То есть ваш шаблон (, который здесь гарантированно не включает совпадение/)после любого/(и до конца пути к файлу, поскольку $также подразумевается ), а не после чего-то, что соответствует $directory.

С zsh -o extendglob,ты можешь сделать:

set -o extendedglob
w=[0-9a-zA-Z] d=[0-9]
print -rC1 -- $directory/$~w##([-_]$~w##)#-$~d(#c1,3)(.$~d(#c1,3))(#c0,3)(#q/)

Который имеет ряд преимуществ перед GNU findодин:

  • будет работать даже на не -системах GNU (устраняет зависимость от GNUfind)
  • работает, даже если $directoryначинается с-
  • дает вам отсортированный список
  • в zsh, то, что соответствует [a-zA-Z0-9], не является случайным и не зависит от локалей, как в find, и соответствует символам, которые, как я полагаю, вы хотите сопоставить, и только им. В findвам понадобится [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789], чтобы получить эквивалент.
  • это работает, даже если $directoryявляется символической ссылкой на каталог (вы можете добавить опцию -Hк findдля этого, хотя ).
  • это работает, даже если пути к файлам (в этом случае содержимое$directory)содержит последовательность байтов, которые не образуют допустимые символы в текущей локали(find's -regex's .*не может сопоставляться с ними, поскольку .соответствует только допустимым символам ).
  • вместо того, чтобы печатать этот список, вы можете использовать его напрямую (в качестве аргументов команды, для циклического перебора и т. д.)
  • вы также можете использовать такие вещи, как (<0-255>~????*)для сопоставления десятичных чисел от 0 до 255, состоящих не более чем из 3 цифр, или (<0-255>~0?*)для этих чисел без ведущего 0, zshшарики являются одним из очень немногих сопоставлений с образцом API, поддерживающие сопоставление диапазонов чисел.
5
28.07.2021, 11:28

Теги

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