2015-05-06 2 views
1

В тексте с линиями подобного формата:Перевести число до и после того, как `/`

3.1 Broadcasting 541/541,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 
3.2 Prefix Computation 590/590,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 

Я хотел бы перевести число до и после / на определенную величину. Например, я woule хотел бы перевести число до / по 1, а число после / по 2 и выше станут:

3.1 Broadcasting 542/543,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 
3.2 Prefix Computation 591/592,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 

Я пытаюсь сделать это с помощью awk:

awk -F'[,/]' '{sub(/\//, " " ($2+1) "/"); sub($2, ($2+1)) }1 

Но моя проблема в том, что я не могу уловить число до /. Как мне улучшить свою команду?

Является ли awk правильным инструментом для этого? Или что-то другое?

Спасибо.

ответ

3

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

Это можно рассматривать как хороший вариант (не самый лучший), потому что это достаточно мощный для выполнения этой задачи, но в этом случае, используя с регулярным выражением и оценить флаг бьет его, как:

perl -pe 's{(\d+)/(\d+)(,)}{($1+1) . "/" . ($2+2) . $3}e' infile 

Это выходы:

3.1 Broadcasting 542/543,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 
3.2 Prefix Computation 591/592,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 

редактирования.К ПОЯСНЕНИЕ команды :

Первые фигурные скобки - это регулярное выражение, соответствующее тексту, а второе - заменяющая строка. Первый соответствует одной или нескольким цифрам между косой чертой и запятой. Флаг /e позволяет выполнять арифметику в заменяемой части, поэтому благодаря группировке я увеличиваю первое число на единицу, второе на два и использую оператор конкатенации (.), чтобы присоединиться к ним и заменить предыдущее совпадение.

+0

Спасибо. (1) Использует ли '{{{{{}} заместительную функцию? Что значит '. 'во втором' {} 'означает? что означает 'e'? (2) Можно ли это сделать аналогично в Python? – Tim

+0

Спасибо. Я не использую perl, но только python. Может ли Python использоваться awk-способом, но также более мощным, чем awk? – Tim

+0

@ Тим: По-моему, да и нет. Да, потому что это намного мощнее, чем 'awk', и Нет, потому что это более многословно и сложно адаптировать его как быстрое и грязное однострочное решение. – Birei

3

Да, awk - правильный инструмент для использования. например с GNU AWK для третьего Arg, чтобы соответствовать():

$ awk 'match($0,/(.*)([0-9]+)\/([0-9]+)(.*)/,a){ $0 = a[1] a[2]+1 "/" a[3]+2 a[4] }1' file 
3.1 Broadcasting 542/543,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 
3.2 Prefix Computation 591/592,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 

С другой awks один подход будет:

$ awk 'match($0,/[0-9]+\/[0-9]+/){ split(substr($0,RSTART,RLENGTH),a,"/"); $0 = substr($0,1,RSTART-1) a[1]+1 "/" a[2]+2 substr($0,RSTART+RLENGTH) }1' file 
3.1 Broadcasting 542/543,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 
3.2 Prefix Computation 591/592,Black,notBold,notItalic,open,TopLeftZoom,0,0,0.0 

В обоих случаях match() изолирует digit(s)/digit(s) часть, так что вы можете работать на том, что сегмент, прежде чем рекомбинировать его с тем, что было до и после него. Решение GNU awk имеет преимущество Capture Groups, сохраненных в 3-м массиве arg, поэтому вам не нужно использовать split()+substr() после match().

Делая 2 похожи, как это возможно, я думаю, что следует делает простак/не поглазеть различия ясно:

Gawk:

awk 'match($0,/(.*)([0-9]+)\/([0-9]+)(.*)/,a) { 
    $0 = a[1] a[2]+1 "/" a[3]+2 a[4] 
}1' file 

Non-простак:

awk 'match($0,/[0-9]+\/[0-9]+/) { 
    # START of what the gawk 3rd arg for match() saves you 
    split(substr($0,RSTART,RLENGTH),b,"/") 
    a[1] = substr($0,1,RSTART-1) 
    a[2] = b[1] 
    a[3] = b[2] 
    a[4] = substr($0,RSTART+RLENGTH) 
    # END of what the gawk 3rd arg for match() saves you 
    $0 = a[1] a[2]+1 "/" a[3]+2 a[4] 
}1' file 

Как вы можете видеть, 3-й аргумент для match() - это всего лишь синтаксический сахар, но МАЛЫЙ сахар в порядке :-).

Смежные вопросы