Как получить 6 цифр из середины пути к файлу?

Как получить 6 цифр из середины пути к файлу?

У меня есть путь к файлу вроде

/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 после /XXXXXXexcept в самом конце, чтобы получить то же поведение, что и решения с использованием 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 цифрами

Связанный контент