Извлечение имени каталога из абсолютного пути с использованием sed или awk - PullRequest
6 голосов
/ 19 декабря 2011

Я хочу разбить эту строку

/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh

до

/home/edwprod/abortive_visit/bin

с использованием sed или awk скриптов? Не могли бы вы помочь в этом?

Ответы [ 6 ]

14 голосов
/ 19 декабря 2011

имя_директория

kent$  dirname "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"
/home/edwprod/abortive_visit/bin

СЭД

kent$  echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"|sed 's#/[^/]*$##'
/home/edwprod/abortive_visit/bin

Grep

kent$  echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"|grep  -oP '^/.*(?=/)'
/home/edwprod/abortive_visit/bin

AWK

kent$  echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"|awk -F'/[^/]*$' '{print $1}'
/home/edwprod/abortive_visit/bin
5 голосов
/ 19 декабря 2011

Может быть команда dirname это то, что вы ищете?

dirname /home/edwprod/abortive_visit/bin/abortive_proc_call.ksh

Или, если вы хотите Sed, посмотрите мое решение:

echo /home/edwprod/abortive_visit/bin/abortive_proc_call.ksh | sed 's/\(.*\)\/.*/\1/'
2 голосов
/ 29 октября 2014

awk + для:

echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh" | awk 'BEGIN{res=""; FS="/";}{ for(i=2;i<=NF-1;i++) res=(res"/"$i);} END{print res}'
1 голос
/ 28 марта 2017

Этот код с awk будет работать точно так же, как и dirname , я думаю.

Он настолько прост и имеет очень низкую стоимость работы.Удачи.

Код

$ foo=/app/java/jdk1.7.0_71/bin/java
$ echo "$foo" | awk -F "/*[^/]*/*$" '
{ print ($1 == "" ? (substr($0, 1, 1) == "/" ? "/" : ".") : $1); }'

Результат

/app/java/jdk1.7.0_71/bin

Тест

  • foo=/app/java/jdk1.7.0_71/bin/java -> /app/java/jdk1.7.0_71/bin
  • foo=/app/java/jdk1.7.0_71/bin/ ->/app/java/jdk1.7.0_71
  • foo=/app/java/jdk1.7.0_71/bin -> /app/java/jdk1.7.0_71
  • foo=/app/ -> /
  • foo=/app -> /
  • foo=fighters/ -> .

Подробнее

Если у вас нет такого ограничителя awk, попробуйте этопуть.

$ echo $foo | awk '{
 dirname = gensub("/*[^/]*/*$", "", "", $0);
 print (dirname == "" ? (substr($0, 1, 1) == "/" ? "/" : ".") : dirname);
 }'
0 голосов
/ 23 августа 2018

В дополнение к ответу Кента, альтернативное решение awk:

awk 'BEGIN{FS=OFS="/"}{NF--}1'

, у которого то же заболевание, что и у Кента.Следующее, несколько длиннее, Awk исправляет все недостатки:

awk 'BEGIN{FS=OFS="/"}{gsub("/+","/")}
     {s=$0~/^\//;NF-=$NF?1:2;$0=$0?$0:(s?"/":".")};1' <file>

Следующая таблица показывает разницу:

| path       | dirname | awk full | awk short |
|------------+---------+----------+-----------|
| .          | .       | .        |           |
| /          | /       | /        |           |
| foo        | .       | .        |           |
| foo/       | .       | .        | foo       |
| foo/bar    | foo     | foo      | foo       |
| foo/bar/   | foo     | foo      | foo/bar   |
| /foo       | /       | /        |           |
| /foo/      | /       | /        | /foo      |
| /foo/bar   | /foo    | /foo     | /foo      |
| /foo/bar/  | /foo    | /foo     | /foo/bar  |
| /foo///bar | /foo    | /foo     | /foo//    |

примечание: dirname - реальноепуть, если вам не нужно обрабатывать их массы, хранящиеся в файле.

0 голосов
/ 18 апреля 2016

Для большинства платформ и оболочек Unix / Linux теперь доступны dirname:

dirname /home/edwprod/abortive_visit/bin/abortive_proc_call.ksh

Использование dirname - самый простой способ, но он не рекомендуется для межплатформенных сценариев, например, в последней версии autoconf документации http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Limitations-of-Usual-Tools.html#Limitations-of-Usual-Tools.

Итак, моя полнофункциональная версия sed альтернативы для dirname:

str="/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"
echo "$str" | sed -n -e '1p' | sed  -e 's#//*#/#g' -e 's#\(.\)/$#\1#' -e 's#^[^/]*$#.#' -e 's#\(.\)/[^/]*$#\1#' -

Примеры:

Работает как dirname:

  • Для пути, подобного /aa/bb/cc, будет напечатано /aa/bb
  • Для пути типа /aa/bb будет напечатано /aa
  • Для пути, подобного /aa/bb/, будет напечатано /aa.
  • Для пути типа /aa/ будет напечатано /aa
  • Для пути типа / будет напечатано /
  • Для пути типа aa будет напечатано .
  • Для пути типа aa/ будет напечатано .

То есть:

  • Работает корректно с трейлингом /
  • Он работает правильно с путями, которые содержат только базовые имена, такие как aa и aa/
  • Он работает правильно с путями, начинающимися с /, и с самим путем /.
  • Он работает корректно с любым $str, если он содержит \n в конце или нет, даже со многими \n
  • Используется кроссплатформенная команда sed
  • Изменяет все комбинации от / (// ///) до /
  • Он не может работать корректно с путями, содержащими новые строки и символы, недопустимые для текущей локали.

Примечание Может быть полезна альтернатива для basename:

echo "$str" | awk -F"/" '{print $NF}' -
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...