Используя sed к массе переименовывают файлы

Цель

Измените эти имена файлов:

  • F00001-0708-RG-biasliuyda
  • F00001-0708-CS-akgdlaul
  • F00001-0708-VF-hioulgigl

к этим именам файлов:

  • F0001-0708-RG-biasliuyda
  • F0001-0708-CS-akgdlaul
  • F0001-0708-VF-hioulgigl

Код Shell

Протестировать:

ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/'

Работать:

ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/' | sh

Мой вопрос

Я не понимаю код sed. Я понимаю что команда замены

$ sed 's/something/mv'

средства. И я понимаю регулярные выражения несколько. Но я не понимаю то, что происходит здесь:

\(.\).\(.*\)

или здесь:

& \1\2/

Первый, мне, просто похож, это означает: "отдельный символ, сопровождаемый отдельным символом, сопровождаемым любой последовательностью длины отдельного символа" - но конечно, существует больше к нему, чем это. До последней части:

& \1\2/

Понятия не имею. Я действительно хочу понять этот код. Помогите мне здесь, парням.

74
задан Daniel Underwood 3 March 2010 в 15:52
поделиться

7 ответов

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

В Ubuntu, OSX (пакет Homebrew переименовать , пакет MacPorts p5-file-rename ) или в других системах с perl rename (prename):

rename s/0000/000/ F0000*

или в системах с переименовать из util-linux-ng, например, RHEL:

rename 0000 000 F0000*

Это намного понятнее, чем эквивалентная команда sed.

Но что касается понимания команды sed, вам может помочь справочная страница sed. Если вы запустите man sed и выполните поиск & (используя команду / для поиска), вы обнаружите, что это специальный символ в s / foo / bar / replacements.

  s/regexp/replacement/
         Attempt  to match regexp against the pattern space.  If success‐
         ful,  replace  that  portion  matched  with  replacement.    The
         replacement may contain the special character & to refer to that
         portion of the pattern space  which  matched,  and  the  special
         escapes  \1  through  \9  to refer to the corresponding matching
         sub-expressions in the regexp.

Следовательно, \ (. \) соответствует первому символу, на который можно ссылаться как \ 1 . Затем . соответствует следующему символу, который всегда равен 0. Тогда \ (. * \) соответствует остальной части имени файла, на которую можно ссылаться как \ 2 .

Строка замены объединяет все вместе, используя & (исходное имя файла) и \ 1 \ 2 , которое является каждой частью имени файла, кроме 2-го { {1}}, который был 0.

Это довольно загадочный способ сделать это, ИМХО. Если по какой-то причине команда переименования была недоступна, и вы хотели использовать sed для переименования (или, возможно, вы делали что-то слишком сложное для переименования?), Будучи более явное выражение в регулярном выражении сделало бы его более читабельным. Возможно, что-то вроде:

ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh

Возможность увидеть, что на самом деле меняется в s / search / replacement /, делает его более читаемым. Кроме того, он не будет удерживать вытягивание символов из вашего имени файла, если вы случайно запустите его дважды или что-то в этом роде.

134
ответ дан 24 November 2019 в 11:49
поделиться

вы у вас есть объяснение sed, теперь вы можете использовать только оболочку, внешние команды не нужны

for file in F0000*
do
    echo mv "$file" "${file/#F0000/F000}"
    # ${file/#F0000/F000} means replace the pattern that starts at beginning of string
done
39
ответ дан 24 November 2019 в 11:49
поделиться

Материал backslash-paren означает, что "во время сопоставления с шаблоном, удерживайте то, что совпадает здесь". Позже, при замене текста, вы можете вернуть эти запомненные фрагменты обратно с помощью "\1" (первый блок со скобками), "\2" (второй блок) и т.д.

2
ответ дан 24 November 2019 в 11:49
поделиться
 ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
0
ответ дан 24 November 2019 в 11:49
поделиться

Команда sed

s/\(.\).\(.*\)/mv & \1\2/

означает замену:

\(.\).\(.*\)

с:

mv & \1\2

точно так же, как обычная команда sed . Однако скобки, маркеры & и \ n немного меняют его.

Строка поиска соответствует (и запоминает как образец 1) одиночному символу в начале, за которым следует единственный символ, за которым следует остальная часть строки (запоминается как образец 2).

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

Итак, эта команда sed создает команду mv на основе исходного файла (для источника) и символов 1 и 3 и далее, эффективно удаляя символ 2 (для пункт назначения). Он выдаст вам серию строк в следующем формате:

mv F00001-0708-RG-biasliuyda F0001-0708-RG-biasliuyda
mv abcdef acdef

и так далее.

6
ответ дан 24 November 2019 в 11:49
поделиться

Если все, что вы действительно делаете, это удаляете второй символ, независимо от того, что это такое, вы можете сделать так:

s/.//2

но ваша команда создает команду mv и передает ее в оболочку для выполнения.

Это не более читабельно, чем ваша версия:

find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh

Четвертый символ удален, потому что find предваряет каждое имя файла символом "./".

0
ответ дан 24 November 2019 в 11:49
поделиться

В круглых скобках указаны конкретные строки для использования с числами с обратной косой чертой.

0
ответ дан 24 November 2019 в 11:49
поделиться