Цель
Измените эти имена файлов:
к этим именам файлов:
Код 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/
Понятия не имею. Я действительно хочу понять этот код. Помогите мне здесь, парням.
Во-первых, я должен сказать, что самый простой способ сделать это - использовать команды предварительного имени или переименования .
В 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 /, делает его более читаемым. Кроме того, он не будет удерживать вытягивание символов из вашего имени файла, если вы случайно запустите его дважды или что-то в этом роде.
вы у вас есть объяснение 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
Материал backslash-paren означает, что "во время сопоставления с шаблоном, удерживайте то, что совпадает здесь". Позже, при замене текста, вы можете вернуть эти запомненные фрагменты обратно с помощью "\1" (первый блок со скобками), "\2" (второй блок) и т.д.
ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
Команда 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
и так далее.
Если все, что вы действительно делаете, это удаляете второй символ, независимо от того, что это такое, вы можете сделать так:
s/.//2
но ваша команда создает команду mv
и передает ее в оболочку для выполнения.
Это не более читабельно, чем ваша версия:
find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh
Четвертый символ удален, потому что find
предваряет каждое имя файла символом "./".
В круглых скобках указаны конкретные строки для использования с числами с обратной косой чертой.