Відповіді:
basename
з GNU coreutils можуть допомогти вам виконати цю роботу:
$ basename /root/video.mp4
video.mp4
Якщо ви вже знаєте розширення файлу, ви можете викликати його basename
за допомогою синтаксису basename NAME [SUFFIX]
, щоб видалити його:
$ basename /root/video.mp4 .mp4
video
Або іншим варіантом буде вирізати все після останньої крапки за допомогою sed
:
$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old
Використовуйте будь-який із наступних способів:
out_file="${in_file##*/}"
out_file="$(basename $in_file)"
out_file="$(echo $in_file | sed 's=.*/==')"
out_file="$(echo $in_file | awk -F"/" '{ print $NF }')"
пс. Ви отримуєте той самий рядок, оскільки у вашому операторі \(.*\.\)
збігається з рядком від початку до точки ( /root/video.
), а потім ви вручну додаєте той, .mp4
який такий же, як у початковій рядку. Ви повинні використовувати s=.*\([^/]*\)=\1=
замість цього.
Оновлення: (Перше виправлено зараз)
Щоб отримати єдине ім’я файлу без розширення, ви можете:
out_file="$(echo $in_file | sed 's=.*/==;s/\.[^.]*$/.new_ext/')"
out_file="$(echo $in_file | sed 's=\([^/]*\)\.[^./]*$=\1.new_ext=')"
out_file="$(echo $in_file | awk -F"/" '{ gsub (/\.[^/.]*$/,".new_ext",$NF);print $NF }'
my.file.tar.gz
.
sed
та awk
. Виправлено. Дякую.
Однією з основ використання регулярного вираження є те, що шаблони жадібні за характером при вказівці підстановки. Хоча відповідь, запропонована @uloBasEI, безумовно, є робочою відповіддю, вона також вимагає використання команди basename. Оригінальне запитання від @Shixons вимагає рішення, використовуючи лише sed.
Перш ніж продовжувати, завжди корисно знати, яка версія sed є цільовим. Я припускаю, що BSD (в комплекті з OSX).
Перш за все, шаблон, запропонований в оригінальному запитанні, не працює, оскільки він фіксує все від початку вхідного рядка до останньої крапки. Без якоря цей пошук проковтне все зліва направо. Таким чином, узгоджений шаблон "/ 1" - це все, що стосується останньої крапки. Навіть ім’я файлу з декількома крапками проковтнеться цілим. Зовсім не бажаний результат.
Перший крок - це створення стратегії виявлення шаблонів. Тут ви хочете позбутися всього зліва від назви файла (ми розберемося з розширенням пізніше):
out_file="$(echo $in_file | sed 's/^\(\/.*\/\)*.*/\1/')"
Пошук відповідає з початку рядка. Він відповідає шаблону "/.*" нуля або більше разів і видаляє все згодом. Друкуємо відповідні шаблони за допомогою "\ 1". Ми не шукаємо глобально; ми шукаємо з початку рядка, вказавши ^ якір.
Ми отримуємо кращу чіткість, включаючи параметр "-E", тому нам не потрібно уникати дужок:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*.*/\1/')"
Отже, тепер у нас є частина зліва. Додамо частину праворуч. Зауважте, що нам потрібно зберігати ліву частину як зразок, оскільки саме так ми можемо вказати, що вона з’являється нульовою чи більше разів. Все, що ми робимо зараз, - це додати шаблон для частини праворуч:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)/\2/')"
Ми друкуємо лише другий збіг, тим самим відкидаючи все, крім назви файлу. Але нам ще потрібно видалити розширення імені файлу.
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2/')"
"$" Наприкінці не є обов'язковим.
Нарешті, щоб додати нове розширення, яке ви просто перегляньте так:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2.mp4/')"
Додаткова оптимізація полягає в тому, щоб зробити першу косу рису вперед необов'язковою для обробки відносних шляхів:
out_file="$(echo $in_file | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2.mp4/')"
Я натрапив на це питання, ледачи, шукаючи шаблон sed для заміни базового імені . Я працюю над позбавленою системою, на якій не встановлена ця команда.
sed 's/\.[^.]*$//'
як у вас є, зазнає невдачі для (прихований).filename
і.
і..
каталоги