Bash :Замена строки/сокращение строки с помощью RegEx (RegEx Fail)

Это старый вопрос, который решался много раз. Просто для полноты картины :У меня была аналогичная проблема, но я хотел передать строки через канал в другую программу. Я использовал xargs .

-L max-lines
   Use at most max-lines nonblank input lines per command line.
   Trailing blanks cause an input line to be logically continued 
   on the next input line.  Implies -x.

, так что cat f1.txt | xargs -L1, кажется, выводит именно то, что вы хотите.

0
28.01.2021, 07:24
2 ответа

В операторе ${var/pattern/replacement}ksh93 шаблон интерпретируется как шаблон подстановочного знака оболочки, а не регулярное выражение.

В ksh93 вы можете переключаться на базовые, расширенные или расширенные регулярные выражения с помощью ~(G), ~(E), ~(X)соответственно, так что вы можете сделать:

var2=${var/~(E)_[0-9]{10}\.tgz$/}

Например. Или используйте его расширенные шаблоны глобусов:

var2=${var/%_{10}([0-9]).tgz/}

(то же, что иvar2=${var%%_{10}([0-9]).tgz})

bash, как и zsh, скопировали оператор ${var/pattern/replacement}из ksh93, но его подстановочные операторы гораздо более ограничены. При включенной опции extglobон поддерживает расширенные операторы ksh88, но не более продвинутые из ksh93 и, в частности, не {x,y}(...).

Тем не менее, он поддерживает +(...). Так что вы могли бы сделать:

shopt -s extglob
var2=${var/%_+([0-9]).tgz/}

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

regexp='^(.*)_[0-9]{10}\.tgz$'
if [[ $var =~ $regexp ]]; then
  var2=${BASH_REMATCH[1]}
else
  var2=$var1
fi

Для полноты, хотя zshскопировал ${var/pattern/replacement}ksh93 и поддерживает расширения подстановочных знаков ksh88 с опцией kshglob, он имеет свои собственные расширенные операторы glob с опцией extendedglob. С ними эквивалентом ERE {x,y}является (#cx,y), так что вы можете сделать:

set -o extendedglob
var2=${var/%_[0-9](#c10).tgz}

(обратите внимание, что из трех оболочек zsh— единственная, где [0-9]соответствует только 0123456789. ksh93 и bash обычно совпадают еще по тысяче символов, таких как ⑱ и т. д. в современных локалях ).

В zshвы также можете выполнять сопоставление регулярных выражений с =~.По умолчанию это ERE, но его можно изменить на PCRE с помощью опции rematchpcre.

set -o rematchpcre
if [[ $var =~ '^(.*)_\d{10}\.tgz\z' ]]; then
  var2=$match[1]
else
  var2=$var
fi

(с ERE или PCRE, соответствует ли \dили [0-9]только 0123456789 или нет, зависит от локали и системной библиотеки регулярных выражений, используемой zsh, например, в bash ).

3
18.03.2021, 22:34

Если вы хотите получить только «резервную копию _пользовательских -данных»:

$ var="backup_user-data_2101220046.tgz"
$ echo "${var%_*}"
backup_user-data
0
18.03.2021, 22:34

Теги

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