Как добавить к числу ближе к концу каждой строки - PullRequest
2 голосов
/ 15 марта 2011

Предположим, есть какой-то текст из файла:

(bookmarks
("Chapter 1 Introduction 1" "#1"
("1.1 Problem Statement and Basic Definitions 2" "#2")
("1.2 Illustrative Examples 4" "#4")
("1.3 Guidelines for Model Construction 26" "#26")
("Exercises 30" "#30")
("Notes and References 34" "#34"))
)

Как добавить 11 к последнему числу в каждой строке, если оно есть, то есть

(bookmarks
("Chapter 1 Introduction 1" "#12"
("1.1 Problem Statement and Basic Definitions 2" "#13")
("1.2 Illustrative Examples 4" "#15")
("1.3 Guidelines for Model Construction 26" "#37")
("Exercises 30" "#41")
("Notes and References 34" "#45"))
)

, используяsed, awk, python, perl, regex ....

Спасибо и всего наилучшего!

Ответы [ 9 ]

5 голосов
/ 15 марта 2011
awk -F'#' 'NF>1{split($2,a,"[0-9]+");print $1 FS $2+11 a[2];next}1' infile

Подтверждение концепции

$ awk -F'#' 'NF>1{split($2,a,"[0-9]+");print $1 FS $2+11 a[2];next}1' infile
(bookmarks
("Chapter 1 Introduction 1" "#12"
("1.1 Problem Statement and Basic Definitions 2" "#13")
("1.2 Illustrative Examples 4" "#15")
("1.3 Guidelines for Model Construction 26" "#37")
("Exercises 30" "#41")
("Notes and References 34" "#45"))
)
4 голосов
/ 15 марта 2011
use strict;
use warnings;
while(my $line = <DATA>){
  $line =~ s/#(\d+)/'#'.($1 + 11)/e;
}
__DATA__
(bookmarks
("Chapter 1 Introduction 1" "#1"
("1.1 Problem Statement and Basic Definitions 2" "#2")
("1.2 Illustrative Examples 4" "#4")
("1.3 Guidelines for Model Construction 26" "#26")
("Exercises 30" "#30")
("Notes and References 34" "#34"))
)

Выход:

(bookmarks
("Chapter 1 Introduction 1" "#12"
("1.1 Problem Statement and Basic Definitions 2" "#13")
("1.2 Illustrative Examples 4" "#15")
("1.3 Guidelines for Model Construction 26" "#37")
("Exercises 30" "#41")
("Notes and References 34" "#45"))
)
2 голосов
/ 15 марта 2011

В Python попробуйте:

import re
m = re.search(r'(?<=#)([0-9]+)',txt)

, чтобы найти следующий номер.Затем установите:

txt = txt[:m.start()] + str(int(m.group())+11) + txt[m.end():]

Повторите это (например, в цикле while), пока search не находит дальнейших совпадений.

Примечание: regExp (?<=#)([0-9]+) соответствует любой последовательностицифр, следующих за # -символом.start() возвращает начальную позицию следующего матча;end() возвращает конечную позицию, а group() - фактическое совпадение.Выражение str(int(m.group()) +11) преобразует сопоставленное число в int-значение, добавляет 11 и повторно преобразует в строку.

1 голос
/ 19 февраля 2015

Emacs Lisp

Предварительные сведения

Здесь мы будем использовать функции из dash и s сторонних библиотек, которые выможно установить в Emacs из MELPA, используя систему пакетов Emacs. Как установить пакеты в Emacs .dash - это библиотека управления списками и деревьями, которая также содержит различные функции, которые делают код более кратким и функциональным .s - библиотека для работы со строками.Когда вы часто пишете код в Elisp, я настоятельно рекомендую установить эти пакеты, чтобы упростить кодирование.

-map - это то же самое, что и mapcar, он просматривает список, вызывает функциюдля каждого элемента и возвращает список со всеми измененными элементами.Например, (-map '1+ '(1 2 3)) ; returns (2 3 4).Однако -map имеет версию анафорического макроса , которая позволяет писать краткий код вместо передачи лямбда-выражений.Анафорические версии начинаются с 2 тире.Например, (--map (+ 10 it) '(1 2 3)) эквивалентно (-map (lambda (x) (+ 10 x)) '(1 2 3)).

->> - это макрос потоков из dash, который похож на состав функции , но в обратном порядке,Например, (number-to-string (-sum (-map '1+ '(1 2 3)))), который возвращает "9", эквивалентен (->> '(1 2 3) (-map '1+) -sum number-to-string).

Строковый подход

Предположим, что вся ваша структура хранится в строке s.Затем вы должны найти каждое вхождение последовательности символов вида #[some_number], используя, возможно, регулярное выражение, и заменить его на число, увеличенное на 11.

(let* ((old (-map 'car (s-match-strings-all "#[0-9]\\{1,3\\}" s)))
       (new (--map (->> it
                        (s-chop-prefix "#")
                        string-to-number
                        (+ 11)
                        number-to-string
                        (s-prepend "#"))
                   old)))
  (s-replace-all (-zip old new) s))

Подход дерева

Но подождитево-вторых, ваша структура рекурсивно заключена в скобки, это s-выражение !Мы можем пройти его как дерево и заменить каждое вхождение строки, начинающейся с # и содержащей числовое значение, новым значением, увеличенным на 11. -tree-map-nodes похоже на -map для деревьев.Функция применяется только тогда, когда предикат возвращает true.IOW, он пропускает некоторые элементы без изменений, если предикат для них не выполняется.

-tree-map-nodes повторяется двумя способами, как по ширине, так и по глубине.Это означает, что он обрабатывает списки как обычные элементы, а первый элемент - весь список.Например, (-tree-map-nodes 'zerop '1+ '(0 (1 (0) 1) 0)) не правильно, он выдаст эту ошибку: *** Eval error *** Wrong type argument: numberp, (0 (1 (0) 1) 0).Вместо этого вы должны сначала проверить, является ли элемент числом.Например, (--tree-map-nodes (and (numberp it) (zerop it)) (1+ it) '(0 (1 (0) 1) 0)) вернется (1 (1 (1) 1) 1).Предположим, ваше дерево находится в переменной q.Тогда решение будет ниже, и оно вернет новое модифицированное s-выражение:

(--tree-map-nodes (and (stringp it)
                       (eq (elt it 0) ?#)
                       (s-numeric? (s-chop-prefix "#" it)))
                  (->> it
                       (s-chop-prefix "#")
                       string-to-number
                       (+ 11)
                       number-to-string
                       (s-prepend "#"))
                  q)
1 голос
/ 20 июля 2011

Этот синтаксис: s-выражения (для краткости sexps), проще всего манипулировать в Lisp и связанных языках, таких как Scheme .Проще всего для сложных задач, то есть;если вы можете предположить, что ваш ввод является достаточно ручным (например, нет "# внутри заголовков глав, новых строк, где вы их иллюстрируете, и т. д.), то для этой задачи предпочтителен инструмент обработки текста (как показано другими ответами).

В Лиспе или Схеме чтение и запись данных в виде структурированных данных так же просто, как (read) и (write data).Другие вещи не так просты, например, нет стандартного способа чтения аргументов командной строки в Лиспе или Схеме.

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

(setq delta (parse-integer (car ext:*args*)))
(defun shift-page (page)
  (format nil "#~D" (+ delta (parse-integer page :start 1))))
(defun shift-pages (entry)
  (let ((title (car entry))
        (page (cadr entry))
        (subentries (cddr entry)))
    (cons title (cons (shift-page page) (mapcar #'shift-pages subentries)))))
(let ((toc (read)))
  (write (cons 'bookmarks (mapcar #'shift-pages (cdr toc)))))
1 голос
/ 16 марта 2011

Python:

import re
file_name="bin/SO/bookmarks.txt"

print "unmodified file:"
with open(file_name) as f:
    for line in f:
        print line.rstrip()

print   

print "modified file:"
i=11
with open(file_name) as f:
    for line in f:
        m=re.match(r'(^.*"#)(\d+)(.*$)',line)
        if m:
            new_line=m.group(1)+str(int(m.group(2))+i)+m.group(3)
            print new_line
        else:
            print line.rstrip()

Вывод:

unmodified file:
(bookmarks
("Chapter 1 Introduction 1" "#1"
("1.1 Problem Statement and Basic Definitions 2" "#2")
("1.2 Illustrative Examples 4" "#4")
("1.3 Guidelines for Model Construction 26" "#26")
("Exercises 30" "#30")
("Notes and References 34" "#34"))
)

modified file:
(bookmarks
("Chapter 1 Introduction 1" "#12"
("1.1 Problem Statement and Basic Definitions 2" "#13")
("1.2 Illustrative Examples 4" "#15")
("1.3 Guidelines for Model Construction 26" "#37")
("Exercises 30" "#41")
("Notes and References 34" "#45"))
)
1 голос
/ 15 марта 2011

Из моего ответа на ваш предыдущий вопрос:

awk '{n = $NF + 11; print "(\"" $0 "\" \"#" n "\")"}' inputfile

или

awk 'BEGIN {q="\x22"} {n = $NF + 11; print "(" q $0 q " " q "#" n q ")"}' inputfile

Это работает с данными, представленными в предыдущем вопросе.Я не могу определить, как вы переходите от этого к примеру, который вы разместили в этом вопросе, поскольку есть разница в том, как скобки вкладываются.Вы также не говорите, существует ли обертка (bookmarks ) в исходном вводе, или если какой-то код, который мы не видим, добавляет его, в то время как другие вещи добавляются.выглядеть немного как XML.Возможно, вам следует использовать реальную вещь и использовать надлежащие инструменты для манипулирования ею.

1 голос
/ 15 марта 2011

В Python

dh = '''"Chapter 1 Introduction 1" "#1"
"1.1 Problem Statement and Basic Definitions 2" "#2"
"1.2 Illustrative Examples 4" "#4"
"1.3 Guidelines for Model Construction 26" "#26"
"Exercises 30" "#30"
"Notes and References 34" "#34"'''

pat = re.compile('^(".+?(\d+)" *"#)\\2" *$',re.M)

def zoo(mat):
    return '%s%s"' % (mat.group(1),str(int(mat.group(2))+11))

print dh
print
print pat.sub(zoo,dh)

результат

"Chapter 1 Introduction 1" "#1"
"1.1 Problem Statement and Basic Definitions 2" "#2"
"1.2 Illustrative Examples 4" "#4"
"1.3 Guidelines for Model Construction 26" "#26"
"Exercises 30" "#30"
"Notes and References 34" "#34"

"Chapter 1 Introduction 1" "#12"
"1.1 Problem Statement and Basic Definitions 2" "#13"
"1.2 Illustrative Examples 4" "#15"
"1.3 Guidelines for Model Construction 26" "#37"
"Exercises 30" "#41"
"Notes and References 34" "#45"

.

Но начиная с предыдущей строки, как показано в вашем другом сообщении:

eh = '''Chapter 3 Convex Functions 97 
3.1 Definitions 98  
3.2 Basic Properties 103'''

pat = re.compile('^(.+?(\d+)) *$',re.M)

def zaa(mat):
    return '"%s" "%s"' % (mat.group(1),str(int(mat.group(2))+11))

print eh
print
print pat.sub(zaa,eh)

результат

Chapter 3 Convex Functions 97 
3.1 Definitions 98  
3.2 Basic Properties 103

"Chapter 3 Convex Functions 97" "108"
"3.1 Definitions 98" "109"
"3.2 Basic Properties 103" "114"

Это все домашнее задание?

.

РЕДАКТИРОВАТЬ:

Я исправил первый код выше

dh = '''(bookmarks
("Chapter 1 Introduction 1" "#1")
("1.1 Problem Statement and Basic Definitions 2" "#2")
("1.2 Illustrative Examples 4" "#4")
("1.3 Guidelines for Model Construction 26" "#26")
("Exercises 30" "#30")
("Notes and References 34" "#34"))
)'''

pat = re.compile('^(\(".+?(\d+)" *"#)\\2" *(\)\)?)$',re.M)

def zoo(mat):
    return '%s%s"%s' % (mat.group(1),str(int(mat.group(2))+11),mat.group(3))

print dh
print
print pat.sub(zoo,dh)

результат

(bookmarks
("Chapter 1 Introduction 1" "#1")
("1.1 Problem Statement and Basic Definitions 2" "#2")
("1.2 Illustrative Examples 4" "#4")
("1.3 Guidelines for Model Construction 26" "#26")
("Exercises 30" "#30")
("Notes and References 34" "#34"))
)

(bookmarks
("Chapter 1 Introduction 1" "#12")
("1.1 Problem Statement and Basic Definitions 2" "#13")
("1.2 Illustrative Examples 4" "#15")
("1.3 Guidelines for Model Construction 26" "#37")
("Exercises 30" "#41")
("Notes and References 34" "#45"))
)
1 голос
/ 15 марта 2011

Если вы можете использовать Ruby (1.9 +)

$ ruby -ne 'puts $_=/#/?$_.gsub(/(.*#)(\d+)(.*)/){"#{$1}"+($2.to_i+11).to_s+"#{$3}"}:$_' file
(bookmarks
("Chapter 1 Introduction 1" "#12"
("1.1 Problem Statement and Basic Definitions 2" "#13")
("1.2 Illustrative Examples 4" "#15")
("1.3 Guidelines for Model Construction 26" "#37")
("Exercises 30" "#41")
("Notes and References 34" "#45"))
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...