
У меня есть путь к файлу вроде
/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz
Я пытаюсь получить только шесть цифр 201906
и напечатать их. Я пытался sed
, awk
но не получилось.
решение1
Предполагая, что это реальные файлы в вашей системе, вы можете легко извлечь часть, предшествующую первой, _
в именах каждого файла, совпадающего с ним *_*.tar.tgz
в каталоге, /dbfs/mnt/dlg2stage/foldername/backupname
используя цикл оболочки:
for pathname in /dbfs/mnt/dlg2stage/foldername/backupname/*_*.tar.tgz; do
name=$( basename "$pathname" )
printf '%s\n' "${name%%_*}"
done
Утилита basename
выдаст вам часть имени файла из пути. Учитывая показанный вами пример, это присвоит строку 201906_load_1_20210623-151602.tar.tgz
переменной name
. Вы также могли бы использовать , name=${pathname##*/}
чтобы сделать то же самое (это расширение параметра удаляет начальную часть строки в $pathname
, вплоть до последнего /
).
Расширение параметра ${name%%_*}
приведет к _*
удалению из значения самой длинной завершающей подстроки $name
. В показанном примере это приведет к удалению первого _
символа и всего, что находится справа от него, оставив подстроку 201906
, которая затем будет выведена с помощью printf
.
решение2
С zsh
:
file=/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz
set -o extendedglob # for (#c6)
first_6_digits_of_file_tail=${(M)${file:t}[0-9](#c6)}
Где ${file:t}
беретхвостфайла (его базовое имя), ${(M)var#pattern}
возвращает часть в начале, $var
которая M
соответствует шаблону.
В POSIX вы можете использовать:
first_6_digits_of_file_tail=$(
LC_ALL=C expr "/$file" : '.*/\([0-9]\{6\}\)[^/]*/*$'
)
LC_ALL=C
игнорировать локаль пользователя и рассматривать все байты как символы (первые 128 в соответствии с ASCII в большинстве систем, включая / и цифры 0123456789), чтобы .
гарантировать [^/]
соответствие байтам и [0-9]
включать только 0123456789. Это не цифры, zsh
где диапазоны основаны на кодовых точках, и zsh рассматривает каждый байт, не являющийся иным образом частью допустимых символов, как если бы он был символом.
Предотвращение /
проблем со значениями, $file
начинающимися с операторов -
или похожими на expr
них, а также гарантия того, что строки содержат хотя бы один оператор, /
как и ожидает регулярное выражение.
Мы не допускаем использования /
s после /XXXXXX
except в самом конце, чтобы получить то же поведение, что и решения с использованием basename
или zsh, $file:t
где базовое имя /foo/bar/
или /foo/bar////
равно bar
.
Будьте осторожны, он возвращает статус завершения «ложь» / «неудача», если совпадений нет, а также если эта последовательность из 6 цифр представляет собой число 0 (как в /path/to/000000_whatever
).
решение3
Я думаю, вы просто хотите напечатать 201906
заданную строку пути. В этом примере эти шесть цифр:первые шесть цифр, перед которыми стоит косая черта.
Я помещаю путь в переменную, чтобы команду было легче читать:
% path_str='/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz'
% echo $path_str | sed 's/.*\/\([0-9]\{6\}\).*/\1/'
201906
Вот как я построил этот матч и замену всед:
\/[0-9]\{6\}
: соответствует косой черте и 6 цифрам\/\([0-9]\{6\}\)
: то же самое, но теперь вгруппа захватаилиподвыражение(косая черта не входит в группу захвата).*\/\([0-9]\{6\}\).*
: соответствует всему, что находится до и после, поэтому...вся линия\1
: при совпадении всей строки используйте ссылку дляпервый(и только) группа захвата для замены всей строки только первыми 6 цифрами