Вы можете скопировать только второй раздел в отдельный образ с помощью этого
dd if=2013-02-09-wheezy-raspbian.img of=second.img bs=512 skip=122880
и после этого можно скопировать вместо раздела на диске
dd if=second.img of=/dev/sdc2 bs=512
или даже одной командой
dd if=2013-02-09-wheezy-raspbian.img of=/dev/sdc2 bs=512 skip=122880
Просто убедитесь, что вы размонтировали /dev/sdc2 перед записью в него.
Если вы должны использовать sed, то одним из способов может быть
Согласно предложениям @Phillipos, он изменен на:
sed -i "" -e '
s/my_string/new_string\
/g;s/\n//w /dev/stdout
s///g
' my_file.json | wc -l
Вы можете заставить редактор vim создавать отчеты в потоковом режиме:
ex -nsc 'redir! >/dev/stderr' -c '%s/pattern/PATTERN/g' -c 'redir END' -c 'wq' my_file
3 substitutions on 2 lines
ex
-режим vim (илиvim -e
)-n
-не создавать файл подкачки-s
-скрипт-c
режим командной строки (или+'command'
)'redir! >/dev/stderr'
-стандартная ошибка перенаправления в оболочку'redir END'
-конец перенаправления. Можно опустить'wq'
-сохранить изменения и выйти из редактора. Если вы замените его на 'q!'
, то сможете получить вывод и сравнить с ожиданиями, не меняя файл.
sed
не считает ничего, кроме номеров строк. Поэтому, если вы хотите использовать sed
и не использовать другие инструменты, как это сделал guest _7, вам нужно научить его считать :
sed -n -i"" ':start
s/my_string/new_string/
Tcont
H
bstart
:cont
p
$!d
x
y/\n_/_\n/
s/_[^_]*/-/g
s/^/0123456789+_0/
:loop
s/\(.\)\(.\)\(.*_.*\)\1-/\1\2\3\2/
s/_+/_10/
s/\(.\)\(.\)\(.*_.*\)\1+/\1\2\3\20/
tloop
s/.*_//
w/dev/stdout
d' my_file.json
Наверное, это слишком очевидно, чтобы объяснять. Нам нужно перебрать замену и подсчитать, добавив строку к H
старому пробелу. Обработка последней строки заключается в отсеивании строк, собранных в удерживаемом пространстве.
Это голая -версия awk для подсчета изменений и затронутых строк:
#! /bin/bash
Awk='
BEGIN { fmtEnd = "Made %d substitutions on %d lines.\n"; }
{
n = gsub (/exit/, "return");
if (n) { Lines++; Count += n; }
print;
}
END { printf (fmtEnd, Count, Lines) > "/dev/stderr"; }
'
awk "${Awk}" doFifo > doFifo.fix
Вывод (stderr )— это просто то, что можно изменить, чтобы упростить восстановление счетчика:
Made 8 substitutions on 6 lines.
GNU/awk имеет расширение -i inplace, но я крайне -консервативен в отношении обновления -in -situ. Мои клиенты много жалуются и утверждают, что их данные всегда на 100% верны, поэтому я храню журналы аудита и каждую версию данных.
Ниже приведен вариант awk, который отмечает каждую измененную строку. Это все еще не производственный уровень :. Я бы хотел, чтобы он принимал шаблон и замену в качестве аргументов, обрабатывал несколько файлов за один запуск, называл выходные файлы на основе входных данных и суммировал по файлам и в целом. Возможно, также разрешите замену массива шаблонов ->.
#! /bin/bash
AwkFull='
BEGIN {
reFix = "exit"; txFix = "return";
fmtEnd = "Made %d substitutions on %d lines.\n";
fmtSub = "\n.... %d Changes on file %s line %d:\n";
fmtSub = fmtSub "Was: %s\nNow: %s\n";
}
{
New = $0;
n = gsub (reFix, txFix, New);
if (n == 0) { print $0; next; }
Lines++; Count += n;
printf (fmtSub, n, FILENAME, FNR, $0, New) > "/dev/stderr";
print New;
}
END { printf (fmtEnd, Count, Lines) > "/dev/stderr"; }
'
awk "${AwkFull}" doFifo > doFifo.fix
Это показывает каждую измененную строку, например:
.... 2 Changes on file doFifo line 64:
Was: (exit) printf 1>&7 '%(%T)T Received exit command\n' -1
Now: (return) printf 1>&7 '%(%T)T Received return command\n' -1
Правка :Преобразование параметров в аргументы команды.
В первой версии шаблон и замещающий текст были встроены в саму команду gsub. Вторая версия упростила их изменение, (a )дав им имена и (b )объявив их в начале кода.
Следующим этапом обобщения кода будет их передача из оболочки. Это легко в awk. Во-первых, удалите строку, определяющую соглашение reFix и txFix (: re
для регулярного выражения и tx
для текста, но вызывайте переменные как угодно, если вы согласны ).
Чтобы получить строки оболочки в переменные awk, существует опция -v
. Таким образом, ваша команда awk становится:
awk -v reFix="exit" -v txFix="return" "${AwkFull}" doFifo > doFifo.fix
и последним шагом к использованию переменных оболочки является использование любой формы подстановки оболочки, например:
awk -v reFix="${1}" -v txFix="${myNew}" "${AwkFull}" doFifo > doFifo.fix
Есть два (а может и больше )минусов:
(1 )awk знает, что /exit/
— это шаблон. В некоторых случаях может потребоваться пояснение синтаксиса :, например,простое совпадение строки -типа /exit/
нужно будет переписать как $0 ~ reFix
. Но awk знает, что первый аргумент gsub()
— это шаблон, так что синтаксис работает без изменений. (Подробнее см. https://www.gnu.org/software/gawk/manual/gawk.html#Strong-Regexp-Constants.)
(2 )Шаблоны в переменных не проверяются синтаксис -при первом чтении программы awk, только когда они используются. Таким образом, введенные пользователем -шаблоны могут легко сломаться в середине выполнения и с неясными сообщениями об ошибках.
Использование Raku (, ранее известного как Perl _6)
raku -pe 'state $k += s:g/ old_string /NEW_STRING/; END put $k;'
ИЛИ
raku -pe 'state $k; s:g/ old_string{++$k} /NEW_STRING/; END put $k;'
Выше приведено решение, написанное на Raku, члене семейства языков программирования Perl. Первое решение — это довольно прямой перевод кода Perl (5 )@terdon, опубликованного в другом месте этой ветки. Второе решение демонстрирует способность Raku выполнять код в блоках {...}
, внутри сопоставителя регулярных выражений m/.../
и/или подстановок s///
. Оба примера записывают количество замен, выполненных в последней строке файла/вывода.
Кратко, raku
вызывается из командной строки с флагами автопечати-pe
(построчно ). Переменная $k
инициализируется ключевым словом state
, что означает, что она объявляется только один раз во время выполнения. После объявления state
значение $k
может быть увеличено либо оператором +=
(, первый пример ), либо оператором приращения ++$k
, предшествующим -, (, вторым примером ). ]. Обратите внимание, что :в левой -половине (, но не в правой -половине )пробела сопоставителя Раку s///
не имеет значения, поэтому вы можете свободно размещать элементы регулярного выражения (для улучшения читаемость ).
И Raku, и Perl (5 )имеют нулевой -индекс, поэтому подсчет в цикле автопечати начинается с нуля. Однако у Raku есть некоторая дополнительная гибкость, если вы отбросите -pe
флаги автопечати и используете -e
с подпрограммой for lines()
вместо :, вы можете выбрать начальное значение вашего счетчика. Допустим, вы хотите выполнить 10 замен :, вы можете взять приведенный ниже код, установить $k=10
и уменьшить с помощью --$k
,проверка последней строки файла, чтобы увидеть, достигли ли вы нуля:
raku -e 'state $k=10; for lines() {S:g/ old_string{--$k} /NEW_STRING/.put; END put $k};'
[Дополнение :Мне не совсем понятно в цикле автопечати raku -pe ''
, почему state $k=10;
не сохраняет, а затем увеличивает/уменьшает начальное значение (в настоящее время поведение должно начинаться с нуля независимо ). Я обновлю этот ответ, как только получу отзыв по этой проблеме].