Команда ip route ls
даст список активных маршрутов и их источников:
caleburn: ~/ >ip route ls
192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.7
default via 192.168.10.254 dev eth0
Попробуйте это (простофиля необходима).
awk '{a=gensub(/.*#([0-9]+)(\").*/,"\\1","g",$0);if(a~/[0-9]+/) {gsub(/[0-9]+\"/,a+11"\"",$0);}print $0}' YourFile
Протестируйте со своим примером:
kent$ echo '(bookmarks
("Chapter 1 Introduction 1" "#1"
("1.1 Problem Statement and Basic Definitions 2" "#2")
("Exercises 30" "#30")
("Notes and References 34" "#34"))
)
'|awk '{a=gensub(/.*#([0-9]+)(\").*/,"\\1","g",$0);if(a~/[0-9]+/) {gsub(/[0-9]+\"/,a+11"\"",$0);}print $0}'
(bookmarks
("Chapter 1 Introduction 12" "#12"
("1.1 Problem Statement and Basic Definitions 13" "#13")
("Exercises 41" "#41")
("Notes and References 45" "#45"))
)
Обратите внимание, что эта команда не будет работать, если эти два числа (например, 1 дюйм и "#1") будут отличаться. или существует больше чисел в той же строке с этим шаблоном (например, 23 дюйма... 32 дюйма... "#123") в одной строке.
ОБНОВЛЕНИЕ
С тех пор @Tim (OP) сказал число, сопровождаемое "
в той же строке могло отличаться, я сделал некоторые изменения на своем предыдущем решении и заставил его работать на Ваш новый пример.
BTW, от примера, я чувствую, что это могла быть структура оглавления, таким образом, я не вижу, как эти два числа могли отличаться. Сначала был бы печатный номер страницы, и 2-й с # будет индекс страницы.Я прав?
Так или иначе Вы знаете свое требование лучше всего. Теперь новое решение, все еще с простофилей (я повреждаю команду в строки, чтобы помочь читать):
awk 'BEGIN{FS=OFS="\" \"#"}{if(NF<2){print;next;}
a=gensub(/.* ([0-9]+)$/,"\\1","g",$1);
b=gensub(/([0-9]+)\"/,"\\1","g",$2);
gsub(/[0-9]+$/,a+11,$1);
gsub(/^[0-9]+/,b+11,$2);
print $1,$2
}' yourFile
протестируйте со своим новым примером:
kent$ echo '(bookmarks
("Chapter 1 Introduction 1" "#1"
("1.1 Problem Statement and Basic Definitions 23" "#2")
("Exercises 31" "#30")
("Notes and References 42" "#34"))
)
'|awk 'BEGIN{FS=OFS="\" \"#"}{if(NF<2){print;next;}
a=gensub(/.* ([0-9]+)$/,"\\1","g",$1);
b=gensub(/([0-9]+)\"/,"\\1","g",$2);
gsub(/[0-9]+$/,a+11,$1);
gsub(/^[0-9]+/,b+11,$2);
print $1,$2
}'
(bookmarks
("Chapter 1 Introduction 12" "#12"
("1.1 Problem Statement and Basic Definitions 34" "#13")
("Exercises 42" "#41")
("Notes and References 53" "#45"))
)
EDIT2 на основе комментария @Tim
(1) FS=OFS = "\" \"#" означают, что разделитель поля и во вводе и выводе удваивает кавычку, пространство, двойная кавычка и в #? Почему указывают двойную кавычку дважды?
Вы правы для разделителя в обеих входных и выходных частях. Это определило разделитель как:
" "#
Существует две двойных кавычки, потому что легче поймать эти два числа, которые Вы хотите (на основе Вашего входа в качестве примера).
(2) В/.* ([0-9] +) $/, $ означает конец строки?
Точно!
(3) В третьем аргументе gensub (), каково различие между "g" и "G"? нет никакого различия между G и g. Проверьте это:
gensub(regexp, replacement, how [, target]) #
Search the target string target for matches of the regular expression regexp.
If "how" is a string beginning with ‘g’ or ‘G’ (short for “global”), then
replace all matches of regexp with replacement.
Это из http://www.gnu.org/s/gawk/manual/html_node/String-Functions.html. можно читать для получения подробного использования gensub.
В отличие от примерно каждого инструмента, который обеспечивает regexp замены, awk не позволяет обратные ссылки такой как \1
в тексте замены. Awk GNU предоставляет доступ к подобранным группам, если Вы используете match
функция, но не с ~
или sub
или gsub
.
Отметьте также это даже если \1
поддерживался, Ваш отрывок добавит строку +11
, не выполняют числовое вычисление. Кроме того, Ваш regexp не совершенно правилен, Вы соответствуете вещам как "42""
и нет "#42"
.
Вот awk решение (предупреждение, непротестированное). Это только выполняет единственную замену на строку.
awk '
match($0, /"#[0-9]+"/) {
n = substr($0, RSTART+2, RLENGTH-3) + 11;
$0 = substr($0, 1, RSTART+1) n substr($0, RSTART+RLENGTH-1)
}
1 {print}'
Это было бы более просто в Perl.
perl -pe 's/(?<="#)[0-9]+(?=")/$1+11/e'
awk
может сделать это, но это не является прямым, даже с помощью backreferencing.
GNU awk имеет (частичный) backreferecing, в форме gensub.
Экземпляры 123"
временно перенесены в \x01
и \x02
отметить их, как не изменено (для sub()
. co
Или Вы могли просто ступить через кандидатов изменения цикла, когда Вы идете, в этом случае, backreferencing и "скобки" не необходимы; но отслеживание индекса символа необходимо.
awk '{$0=gensub(/([0-9]+)\"/, "\x01\\1\"\x02", "g", $0 )
while ( match($0, /\x01[0-9]+\"\x02/) ) {
temp=substr( $0, RSTART, RLENGTH )
numb=substr( temp, 2, RLENGTH-3 ) + 11
sub( /\x01[0-9]+\"\x02/, numb "\"" )
} print }'
Вот иначе, с помощью gensub
и массив split
и \x01
как разделитель полей (для разделения).. \x02 отмечает элемент массива как кандидата на арифметическое дополнение.
awk 'BEGIN{ ORS="" } {
$0=gensub(/([0-9]+)\"/, "\x01\x02\\1\x01\"", "g", $0 )
split( $0, a, "\x01" )
for (i=0; i<length(a); i++) {
if( substr(a[i],1,1)=="\x02" ) { a[i]=substr(a[i],2) + 11 }
print a[i]
} print "\n" }'
"\x01\\1\"\x02"
средний? Я все еще не понимаю \x01
и \x02
. (2), насколько отличающийся возврат $0
gensub
и $0
как последний аргумент gensub
?
– StackExchange for All
20.11.2011, 23:04
\x01
и \x02
используются в качестве маркеров замены. Эти значения очень вряд ли будут в любом файле обычного текста, таким образом, они будут одинаково "очень" безопасны использовать (т.е. не встретиться со столкновением с существующими ранее).. Они - просто временные маркировки.. Ре $0=gensub(... $0)
.. посмотрите эту Обработку строк ссылки Функции, но таким образом: Это (gensub) возвращает измененную строку как результат функции, и исходная целевая струна не поменялась.... $0=
просто изменяет исходную цель..
– Peter.O
23.11.2011, 13:37
Поскольку решения в (g) awk кажутся довольно сложными, я хотел добавить альтернативное решение в Perl:
perl -wpe 's/\d+(?=")/$&+11/eg' < in.txt > out.txt
Объяснение:
-w
включает предупреждения (которые будут предупреждать вас возможных нежелательных эффектов). -p
подразумевает цикл вокруг кода, который работает аналогично sed или awk, автоматически сохраняя каждую строку ввода в переменной по умолчанию $ _
. -e
сообщает Perl, что программный код следует в командной строке, а не в файле сценария. s /.../.../
) на $ _
, где последовательность цифр, если за ней следует "
, будет заменена последовательностью, интерпретируемой как число в добавлении плюс 11. (? = Шаблон)
ищет "
, не принимая его в соответствие, поэтому нам не нужно повторять его при замене. Тогда переменная MATCH $ &
в замене будет содержать только число. / e
регулярного выражения указывает perl
«выполнить» замену как код, а не принимать ее как строку. / g
делает замену «глобальной», повторяя ее при каждом совпадении в строке. Переменная MATCH $ &
, к сожалению, ухудшит производительность кода в версиях Perl до 5.20.Более быстрое (и не намного более сложное) решение могло бы использовать вместо этого группировку и обратную ссылку $ 1
:
perl -wpe 's/(\d+)?="/$1+11/eg' < in.txt > out.txt
И если прогнозируемое утверждение выглядит слишком запутанным, вы также можете явно заменить кавычки:
perl -wpe 's/(\d+)"/$1+11 . q{"}/eg' < in.txt > out.txt
awk -F'#'
, кажется, что Вы только хотите сделать изменение на части после '#'? – Kent 20.11.2011, 02:10FS=OFS="\" \"#"
подразумевайте, что разделитель поля и во вводе и выводе удваивает кавычку, пространство, двойная кавычка и в #? почему указывают двойную кавычку дважды? (2) в/.* ([0-9]+)$/
, делает$
иметь в виду конец строки? (3) в третьем аргументе gensub (), между чем различие"g"
и"G"
? – StackExchange for All 20.11.2011, 22:56