Стандартный Unix util для разделения “foo.bar.baz” на “foo.bar” + “.baz”?

Можно запустить скрипты Python путем создания их исполняемым файлом (chmod +x test.py) и создание #!/usr/bin/env python первая строка. После того как Вы делаете это, работая test.py args вызовет Python для запущения скрипта. Читайте о хижине, если Вы хотите узнать больше.

4
28.06.2013, 03:23
5 ответов

Не может быть команд, которые устанавливают переменные Вашей оболочки, потому что переменные являются чем-то внутренним к процессу оболочки, таким образом, другая команда, живущая в ее собственном процессе, не могла возможно изменить это.

С Вашей оболочкой можно сделать вещи как:

var=$(some-command)

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

Один метод похож:

eval "$(some-command)"

Где выходные вещи некоторой-команды как:

var1='something' var2='someotherthing'

Но перед выяснением нет такой стандартной команды, которая берет путь и разделяет его на dir, базовое имя и расширение (независимо от того, что это означает) таким способом.

Теперь сами оболочки могут иметь внутренние функции этого. Например, csh и zsh имейте модификаторы, которые могут дать Вам голову, хвост, расширение. Как в zsh:

file=/path/to/foo.bar/
head=$file:h
tail=$file:t
ext=$file:e
rest=$file:r

Теперь можно хотеть рассмотреть то, как что это должно быть для файла . или .., /, .bashrc или foo.tar.gz?

Теперь при поиске стандартного синтаксиса POSIX затем у Вас уже есть он (почти): rest=${file%.*}. ${file#$rest} zsh конкретный. В синтаксисе POSIX Вам нужно ext=${file#"$rest"}, иначе $rest взят в качестве шаблона. Остерегайтесь, который не может сделать то, что Вы хотите если $file содержит путь с / символы (как foo.d/bar).

2
27.01.2020, 20:54
  • 1
    Спасибо за разъяснение... Я вижу, что мне были бы нужны две команды (или одна команда с двумя различными "режимами" операции), и два вызова, чтобы сделать то, что я хочу. И также для указателя о двойном заключении в кавычки $rest часть. –  kjo 28.06.2013, 03:41
  • 2
    Хорошо упомянутый ответ! Я был бы +2, если я мог. –  slm♦ 28.06.2013, 04:07

Можно использовать просто строковые функции парсинга, которые включены в Bash, чтобы сделать что-то очень близко к тому, что Вы хотите:

$ F="foo.bar.baz"

$ echo ${F%.*}
foo.bar

$ echo ${F/*./.}
.baz

Таким образом, Вы могли соединить его как так:

$ $ F="foo.bar.baz"

$ stem=${F%.*}
$ ext=${F/*./.}

echo "${stem}${ext}"
foo.bar.baz

выборки из страницы справочника Bash

$ {F %.*}
${parameter%word}
${parameter%%word}
   Remove  matching suffix pattern.  The word is expanded to produce a pattern 
   just as in pathname expansion.  If the pattern matches a trailing portion
   of the expanded value of parameter, then the result of  the  expansion  is
   the expanded  value  of  parameter with the shortest matching pattern (the
   ``%'' case) or the longest matching pattern (the ``%%'' case) deleted.  If
   parameter is @ or *, the pattern removal operation is applied  to  each
   positional parameter  in turn, and the expansion is the resultant list.  
   If parameter is an array variable subscripted with @ or *, the pattern
   removal operation is applied to each member of the array in  turn,  and  
   the  expansion  is  the resultant list.
${/*./.}
${parameter/pattern/string}
   Pattern  substitution.   The pattern is expanded to produce a pattern just
   as in pathname expansion.  Parameter is expanded and the longest match of 
   pattern against its value is replaced with string.  If pattern  begins 
   with  /, all  matches  of  pattern are replaced with string.  Normally
   only the first match is replaced.  If pattern begins with #, it must match
   at the beginning of the expanded value of parameter.  If pattern  begins
   with  %,  it  must match  at the end of the expanded value of parameter.
   If string is null, matches of pattern are deleted and the / following
   pattern may be omitted.  If parameter is @ or *, the substitution operation
   is  applied  to  each  positional  parameter in turn, and the expansion 
   is the resultant list.  If parameter is an array variable subscripted
   with @ or *, the substitution operation is applied to each member of the
   array in turn, and the expansion  is  the resultant list.

Можно читать об этих функциях в странице справочника Bash.

3
27.01.2020, 20:54
  • 1
    С чем было неправильным ${F/*./.}? –  rici 27.06.2013, 22:25
  • 2
    @rici - который работает также. Не попробовал его. –  slm♦ 27.06.2013, 22:40
  • 3
    @rici - обновляет ответ, спасибо за обратную связь. –  slm♦ 27.06.2013, 22:54
  • 4
    Важно отметить, что этим решением является совместимый с оболочкой POSIX, который означает, что это должно работать в какой-либо оболочке, которая поддерживает Станд. IEEE 1 003,1 Командных языка Shell (см. pubs.opengroup.org/onlinepubs/9699919799/utilities / …), –  bonsaiviking 28.06.2013, 00:10
  • 5
    @bonsaiviking, нет. ${F/*./.} не POSIX. –  Stéphane Chazelas 28.06.2013, 00:31

Если строки не содержат новые строки:

start cmd:> echo foo.bar.baz | sed 's/\(^.*\)\(\.[^\.]*$\)/\1/'
foo.bar

start cmd:> echo foo.bar.baz | sed 's/\(^.*\)\(\.[^\.]*$\)/\2/'
.baz
0
27.01.2020, 20:54
  • 1
    , если они не содержат новые строки или в зависимости от echo реализация, не содержите обратные косые черты, или не вещи как -n или -nene. Кроме того, если имя файла не будет иметь никакой точки, то оба возвратят имя файла. Вероятно, также придется рассмотреть случаи, где файл является "foo.d/bar", например. –  Stéphane Chazelas 27.06.2013, 23:25

Я не видел стандартных команд Unix для этого. Я использовал это в рамках сценариев оболочки:

fullname=foo.bar.baz
basename="$(python -c "import os; print os.path.splitext('"$fullname"')[0]")"
extension="$(python -c "import os; print os.path.splitext('"$fullname"')[1]")"

поскольку я нахожу это более легким разобраться, чем регулярные выражения. YMMV.

0
27.01.2020, 20:54
  • 1
    Принятие $fullname не содержит одинарной кавычки или обратной косой черты или символов новой строки –  Stéphane Chazelas 27.06.2013, 23:28
  • 2
    @StephaneChazelas Да, в этом случае Вы лучше делаете все это в рамках Python. –  Anthon 27.06.2013, 23:39

Принятие "foo.bar". допустимый вывод, если расширение отсутствует и что всегда будет два или три периода, это должно работать с awk:

basename='foo.bar.baz'
stem=$(echo $basename | awk '{ split($1,a,"."); print a[1] "." a[2]; }')
ext=$(echo $basename | awk '{ split($1,a,"."); print "." a[3]; }');
echo $stem$ext
0
27.01.2020, 20:54

Теги

Похожие вопросы