Получить содержимое подстановочного знака / звездочки - PullRequest
1 голос
/ 26 сентября 2019

Возможно ли получить последнее содержимое шаблона?

Допустим, у меня есть список файлов:

foo-15.csv
foo-32.csv
foo-65.csv

и т. Д.

Возможно ли эточтобы получить доступ к подстановочному содержимому при использовании:

for file in foo-*.csv; do
    echo wildcard_content
done

, чтобы печатать

 15
 32
 65

примечание: Я не хочу использовать строковые манипуляции с $file.Выше приведен простой пример, и глобулярное выражение может быть чем угодно.Можно ли получить доступ к содержанию подстановочных знаков?Содержимое подстановочного знака хранится в определенной в bash переменной, которую я могу вызвать, или что-то в этом роде?

Ответы [ 3 ]

3 голосов
/ 26 сентября 2019
#! /bin/bash

shopt -s nullglob

for file in *.csv; do
    echo "${file%.csv}"
done

Вы можете удалить часть .csv, как указано выше.

Вы можете понять работу % из документов .

В нем говорится:

$ {параметр% word}
$ {параметр %% word}
Слово расширяется для создания шаблона и сопоставляется в соответствии с правилами, описанными ниже (см. Сопоставление шаблонов),Если шаблон соответствует завершающей части расширенного значения параметра, то результатом расширения является значение параметра с самым коротким совпадающим шаблоном (случай «%») или самым длинным совпадающим шаблоном (случай «%%»)удален.Если параметр равен «@» или «», операция удаления шаблона применяется по очереди к каждому позиционному параметру, и расширение является результирующим списком.Если параметром является переменная массива, подписанная с помощью «@» или «», операция удаления шаблона применяется к каждому члену массива по очереди, и расширение является результирующим списком.

@Sorin объяснил, почему использовать shopt -s nullglob в комментариях.Для дальнейшего объяснения обратитесь к документам

0 голосов
/ 26 сентября 2019

Я полагаю, что вы ищете то, что напоминает BASH_REMATCH.

Доступен дополнительный двоичный оператор =~, имеющий тот же приоритет, что и == и !=,Когда она используется, строка справа от оператора считается расширенным регулярным выражением и соответствующим образом сопоставляется (как в регулярном выражении (3)).Возвращаемое значение равно 0, если строка соответствует шаблону, и 1 в противном случае.Если регулярное выражение синтаксически неверно, возвращаемое значение условного выражения равно 2. Если включена опция оболочки nocasematch, сопоставление выполняется без учета буквенных символов.Любая часть шаблона может быть заключена в кавычки, чтобы ее можно было сопоставить как строку. Подстроки, соответствующие подвыражениям в скобках внутри регулярного выражения, сохраняются в переменной массива BASH_REMATCH.Элемент BASH_REMATCH с индексом 0 является частью строки, соответствующей всему регулярному выражению.Элемент BASH_REMATCH с индексом n является частью строки, соответствующей n-му подвыражению в скобках.

К сожалению, шаблоны глобусов и регулярные выражения не совпадают (см. этот вопрос и эта статья linuxjournal ).Тем не менее, мы можем сделать перевод один-к-одному:

|-------+-------+---------------------------------------|
| glob  | regex | remark                                |
|-------+-------+---------------------------------------|
| *     | [^/]* | filenames don't have a /              |
| **/   | .*/   | ** repreensts full paths (end with /) |
| ?     | [^/]  | filenames don't have a /              |
| [...] | [...] | the character groups are the same     |
|-------+-------+---------------------------------------|

Вы должны быть осторожны, поскольку некоторые символы имеют особые значения в регулярных выражениях, но не в глобальных выражениях.(Например, ., +):

Итак, в примере с OP вы можете сделать это:

for file in foo-*.csv; do
   [[ "${file}" =~ foo-([^/]*)[.]csv ]]
   echo "${BASH_REMATCH[1]}"
done

Или более сложный пример:

for file in *-substring-[0-3a-9]-foo?.file
     [[ "${file}" =~ ([^/]*)-substring-([0-3a-9])-foo(.)[.]file ]]
     echo "${BASH_REMATCH[1]} ${BASH_REMATCH[2]} ${BASH_REMATCH[3]}"
done
0 голосов
/ 26 сентября 2019

Аналогично ответу @Mihir, но если вы хотите получить доступ ко всему списку файлов за одну итерацию, тогда

files=(*.csv)
for file in "${files[@]}"; do
    echo ${files[@]//.csv/}
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...