Как использовать shell glob так, как это делает *в регулярном выражении

Если ветки нет,

$ git status
On branch blah_gone_now
Your branch is based on 'origin/1234/blah_gone_now', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)

$ git branch --unset-upstream

Затем мастер оформления заказа или что вам нужно

0
03.07.2020, 18:46
2 ответа

Единственный способ найти совпадение с одним и тем же регулярным выражением в базовой подстановке — это сделать:

cp title[.]txt title.*.txt destination_folder/

Если предположить, что файлы существуют (или установить значение nullglob, то при отсутствии файла будет генерироваться ошибка cp ).

Или:

$ ksh -c '
      set -- ~(N)title[.]txt ~(N)title.*.txt
      [ $# -ge 1 ] && cp "$@" dir/
  '

Или:

$ bash -O nullglob -c '
    set -- title[.]txt title.*.txt
    [ $# -ge 1 ] && cp "$@" dir/
  '

Или аналогично в других оболочках.


Почему

Технически нет никакого возможного эквивалента регулярного выражения *в глобусе.

Главным образом потому, что регулярное выражение single *не имеет смысла. Оно получает значение, когда перед ним что-то есть, и тогда оно означает повторение предыдущего токена (чего-то)0или более раз.

То, что имеет точный эквивалент, :регулярное выражение .*точно эквивалентно глобусу *.

Эквивалент регулярного выражения типа title(\..*)*\.txtблизок к title.*.txt.

начало и конец

Я предполагаю, что точное регулярное выражение, которое вы должны были написать для grep, это:

^title(\..*)*\.txt$

Что будет соответствовать вашим утверждениям , начинающимся со слова «название». и , оканчивающиеся на ".txt" . Начало должно обозначаться ^, а окончание — $в регулярном выражении.

Начало и конец по умолчанию включены в глобус.

точка

Точка, являющаяся специальным символом в регулярном выражении, должна быть экранирована:\..

Точка не является особой в глобусе и не нуждается в экранировании.

необязательный символ

Но нет способа выразить необязательный символ в глобусе (basic ).

A (c|d)?, что в регулярном выражении означает :«необязательный c или d», или, проще говоря, :символ cилиdноль или один раз ,не имеет эквивалента в базовом глобусе. Чтобы получить это, вам нужно использовать расширенный подстановочный знак. Синтаксис для дополнительной строки::

?(c|d)        # glob

Так:

?(.*)         # zero or once `?( )` a dot followed by anything (`*`).

Означает :необязательное соответствие точке, за которой следует что-либо (даже пустое ).

И весь шар был бы:

title?(.*).txt            # only in extended globbing.

Способ установки расширенного диапазона подстановок для каждой оболочки (не является переносимым):

  • ksh : on by default, no need to set anything.
  • bash : shopt -s extglob
  • zsh : set -o extendedglob

портативный (почти)

Единственный способ найти совпадение с одним и тем же регулярным выражением в базовой подстановке — это сделать:

echo title[.]txt title.*.txt 

nullglob

Но все приведенные выше сопоставления предполагают, что какое-то совпадение будет результатом расширения шара. Если может случиться так, что глобус не найдет совпадения (, например title[.]txt, не найдет title.txtфайл ), тогда вам также следует установить параметр оболочки nullglob, чтобы удалить глобус (, а не оставить его. в командной строке ).

Но это тоже не переносимо:

  • ksh :Не имеет опции nullglob. Работает только при использованииecho ~(N)title?(.*).txt
  • баш:shopt -s nullglob.
  • зш:set -o NULL_GLOBилиset -G

Кроме того, если установлен nullglob и шаблон не соответствует, cpбудет генерировать ошибку, так как cp "увидит" эту командную строку:

cp  dir/

Где не указан источник.

фейлглоб

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

cp title[.]txt title?(.*).txt dir/

завершится ошибкой, если произойдет сбой любого из двух шаблонов.

Финал

Единственный способ заставить cp работать даже без совпадения и без получения ошибки от cp:

$ bash -O nullglob -c '
    set -- title[.]txt title.*.txt
    [ $# -ge 1 ] && cp "$@" dir/
  '

$ ksh -c '
      set -- ~(N)title[.]txt ~(N)title.*.txt
      [ $# -ge 1 ] && cp "$@" dir/
  '
0
18.03.2021, 23:22

В стандартных подстановочных знаках оболочки нет эквивалента, но в некоторых оболочках есть некоторые расширения для этого:

зш

в zsh, это оператор #, активируемый опцией extendedglob:

set -o extendedglob # best in ~/.zshrc
cp -- *title(.*)#.txt* dest/

Вы можете использовать ERE или PCRE в подстановках, используя квалификатор eglob:

cp -- *(e['[[ REPLY =~ "title(\..*)*\.txt" ]]']) dest/

(выпустить set -o rematchpcreдля использования PCRE вместо ERE или использовать -pcre-matchвместо =~послеzmodload zsh/pcre)

кш

В кш (все версии ), x*есть*(x):

cp -- *title*(.*).txt* dest/

баш

bash поддерживает операторы ksh с опцией extglob:

shopt -s extglob
cp -- *title*(.*).txt* dest/

кш93

ksh93может использовать регулярные выражения в своих глобах:

cp -- *~(E:title(\..*)*\.txt)* dest/

(Eдля E расширенные регулярные выражения здесь ).

Он также может преобразовывать ERE в шаблоны глобусов с помощью:

$ printf '%P\n' 'title(\..*)*\.txt'
*title*(\.*)\.txt*

(эти обратные косые черты здесь излишни)

3
18.03.2021, 23:22

Теги

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