Перевести часть строки - PullRequest
       3

Перевести часть строки

4 голосов
/ 25 февраля 2012

У меня есть куча файлов, которые я перемещаю из одной вики (на основе Markdown) в другую (на основе Creole). Я написал пару сценариев sed для таких вещей, как конвертирование форматов ссылок и форматов заголовков. Но новая вики допускает структуру каталогов, и я бы лучше использовал ее, чем структуру псевдо-каталогов, которая у меня есть сейчас. Я уже переименовал файлы, но мне нужно преобразовать все ссылки из _ с разделителями в / с разделителями.

Базовая информация:

Creole link: [[url]] [[url|name]]

Я хочу конвертировать только те ссылки, которые не содержат . или /.

Я был бы очень признателен, если бы вы объяснили, что означает указанная вами команда, чтобы я мог извлечь из нее урок.


Пример

this is a line with a [[Link_to_something]] and [[Something_else|something else]]
this site is cool [[http://example.com/this_page]]

до

this is a line with a [[Link/to/something]] and [[Something/else|something else]]
this site is cool [[http://example.com/this_page]]

Что я пробовал

y/// работает только на всю строку.

s//\u\2 поддерживает только переводы регистра.

Ответы [ 3 ]

3 голосов
/ 25 февраля 2012

Думаю, я бы использовал Perl.Это можно сделать в виде одной строки, таким образом:

perl -pe 's{\[\[([^/.|]+)(|[^]]+)?\]\]}{$x=$1;$y=$2;$x=~s%_%/%g;"[[$x$y]]"}gex;' <<'EOF'
this is a line with a [[Link_to_something]] and [[Something_else|something else]]
this site is cool [[http://example.com/this_page]]
EOF

Вывод этого:

this is a line with a [[Link/to/something]] and [[Something/else|something else]]
this site is cool [[http://example.com/this_page]]

Вопрос о том, хороший ли это стиль и т. Д., Полностью открыт для обсуждения.

Я объясню эту версию кода, которая изоморфна приведенному выше коду:

perl -e 'use strict; use warnings;
         while (my $line = <>)
         {
             $line =~ s{ \[\[ ([^/.|]+) (|[^]]+)? \]\] }
                       { my($x, $y) = ($1, $2); $x =~ s%_%/%g; "[[$x$y]]" }gex;
             print $line;
         } '

Цикл while в основном то, что -p предоставляет в первой версии.Я явно назвал входную переменную $line вместо использования неявного $_, как в первой версии.Мне также пришлось объявить $x и $y из-за use strict; use warnings;.

Команда замены принимает форму s{pattern}{replace}, поскольку в самих регулярных выражениях есть косые черты.Модификатор x допускает (несущественные) пробелы в двух частях, что облегчает разметку.Модификатор g повторяет подстановку так часто, как соответствует шаблону.Модификатор e говорит: «обрабатывать правую часть подстановки как выражение».

Соответствующий шаблон ищет пару открытых квадратных скобок, а затем запоминает последовательность символов, отличную от /, . или |, за которыми необязательно следует | и последовательность символов, отличных от ], заканчивающаяся парой квадратных скобок.Два захвата: $1 и $2.

Выражение замены сохраняет значения $1 и $2 в переменных $x и $y.Затем он применяет более простую замену к $x, превращая подчеркивания в косые черты.Тогда значением результата является строка [[$x$y]].Вы не можете изменить $1 или $2 непосредственно в выражении замены.И внутренние s%_%/%g; клобберы $1 и $2, поэтому мне понадобились $x и $y.

Может быть другой способ сделать это - это Perl, так что TMTOWTDI:есть больше чем один способ сделать это.Но это по крайней мере работает.

2 голосов
/ 25 февраля 2012

Это может работать для вас:

awk -vORS='' -vRS='[[][[][^].]*[]][]]' '{gsub(/_/,"/",RT);print $0 RT}' file
this is a line with a [[Link/to/something]] and [[Something/else|something else]]
this site is cool [[http://example.com/this_page]]
  • Установить разделитель выходной записи на ноль
  • Установить разделитель записей на [[...]] (где ... несодержат ..
  • Заменить все _ в том, что помещено в переменную разделителя записей RT на / '
  • Печать объединенной записи и разделителя записейто есть $0 RT

Это решение sed:

sed 's/\[\[[^].]*]]/\a\n&\a\n/g' file |
sed '/^\[\[[^]]*\]\]\a/y/_/\//;H;$!d;g;s/\a\n//g;s/.//'
this is a line with a [[Link/to/something]] and [[Something/else|something else]]
this site is cool [[http://example.com/this_page]]
  • Объем [[...]] с \a\n выбран NB \aкак маловероятный символ в файле.
  • Переведите '_' в / в строках, начинающихся с [[
  • Удалите все вхождения \a\n 's

Если у вас есть GNU sed, это будет делать:

sed '/\[\[[^].]*]]/{s||'\''$(sed "y/_/\\//" <<<"&")'\''|g;s/.*/echo '\''&'\''/}' file 
this is a line with a [[Link/to/something]] and [[Something/else|something else]]
this site is cool [[http://example.com/this_page]]
1 голос
/ 25 февраля 2012

Вы можете использовать python, чтобы упростить регулярное выражение:

$ python3 -c '
> import re
> import sys
> for line in sys.stdin:
>     print(re.sub(r"\[\[(?!http).*?\]\]", lambda m:m.group(0).replace("_", "/"), line), end="")
> ' <input.txt

this is a line with a [[Link/to/something]] and [[Something/else|something else]]
this site is cool [[http://example.com/this_page]]

Примечание : $ and > в начале строки - командная строка.


Вы также можете сделать это в vim визуально:

/\[\[\(http\)\@!.\{-}\]\]
:%s@@\=substitute(submatch(0), '_', '/', '')@g
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...