sed заменяет пробел символом подчеркивания между двумя строками - PullRequest
0 голосов
/ 10 февраля 2019

У меня есть файл, который содержит такие строки:

some thing <phrase>a phrase</phrase> some thing else <phrase>other stuff</phrase>

Мне нужно заменить все пробелы между тегами <phrase> на подчеркивание.Поэтому в основном мне нужно заменить все пробелы между > и </ подчеркиванием.Я пробовал много разных команд в sed, awk и perl, но не смог заставить что-либо работать.Ниже приведены некоторые команды, которые я пробовал.

sed 's@>\s+[</]@_@g'

perl -pe 'sub c{$s=shift;$s=~s/ /_/g;$s}s/>.*?[<\/]/c$&/ge'

sed 's@\(\[>^[<\/]]*\)\s+@\1_@g'

awk -v RS='\\[>^[<\]/]*\\]' '{ gsub(/\<(\s+)\>/, "_", RT); printf "%s%s", $0, RT }' infile

Я смотрю на эти 2 вопроса, пытаясь изменить ответы, чтобы использовать нужные мне символы.
заменяет пробел только на тире только между определенными шаблонами символов

https://unix.stackexchange.com/questions/63335/how-to-remove-all-white-spaces-just-between-brackets-using-unix-tools

Может кто-нибудь помочь, пожалуйста?

Ответы [ 6 ]

0 голосов
/ 09 апреля 2019

если ваши данные в 'd' от gnu sed;

sed -E ':b s/<(\w+)>([^<]*)\s([^<]*)(<\/\1)/<\1>\2_\3\4/;tb' d
0 голосов
/ 10 февраля 2019

С GNU awk для мульти-символьных RS и RT:

$ awk -v RS='</?phrase>' '!(NR%2){gsub(/\s+/,"_")} {ORS=RT}1' file
some thing <phrase>a_phrase</phrase> some thing else <phrase>other_stuff</phrase>
0 голосов
/ 10 февраля 2019

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

sed -E 's/<phrase>|<\/phrase>/\n&/g;ta;:a;s/^([^\n]*(\n[^\n ]*\n[^\n]*)*\n[^\n]*) /\1_/;ta;s/\n//g' file

Разделяйте теги, вставляя символы новой строки.Итеративно подставляйте пробелы между парами символов новой строки подчеркиванием.Если совпадений больше нет, удалите введенные символы новой строки.

0 голосов
/ 10 февраля 2019

Еще один Perl, заменяющий теги <phrase>

$ export a="some thing <phrase>a phrase</phrase> some thing else <phrase>other stuff</phrase>"

$ echo $a | perl -lne ' s/(?<=<phrase>)(.+?)(?=<\/phrase>)/$x=$1;$x=~s{ }{_}g;sprintf("%s",$x)/ge ;  print '
some thing <phrase>a_phrase</phrase> some thing else <phrase>other_stuff</phrase>

$

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

Спасибо @haukex, продолжая сокращаться

$ echo $a | perl -lne ' s/(?<=<phrase>)(.+?)(?=<\/phrase>)/$x=$1;$x=~s{ }{_}g;$x/ge ;  print '
some thing <phrase>a_phrase</phrase> some thing else <phrase>other_stuff</phrase>

$
0 голосов
/ 10 февраля 2019

Не использовать регулярные выражения для анализа XML / HTML.

use warnings;
use 5.014;  # for /r modifier
use Mojo::DOM;

my $text = <<'ENDTEXT';
some thing <phrase>a phrase</phrase> some thing else <phrase>other stuff</phrase>
ENDTEXT

my $dom = Mojo::DOM->new($text);
$dom->find('phrase')->each(sub { $_->content( $_->content=~tr/ /_/r ) });
print $dom;

Вывод:

some thing <phrase>a_phrase</phrase> some thing else <phrase>other_stuff</phrase>

Обновление: Mojolicious даже содержит немного сахара, который позволяет втирать этот код в oneliner:

$ perl -Mojo -pe '($_=x($_))->find("phrase")->each(sub{$_->content($_->content=~tr/ /_/r)})' input.txt
0 голосов
/ 10 февраля 2019

Мне нужно заменить все пробелы между > и </ подчеркиванием.

Это на самом деле не будет делать то, что вы хотите, потому что, например, в

some thing <phrase>a phrase</phrase> some thing else <phrase>other stuff</phrase>
                  ^^^^^^^^^^^      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

подстроки "между > и </" охватывают больше, чем вы думаете (отмечено ^ выше).

Я думаю, что самый простой способ выразить ваши требования в Perl - это

perl -pe 's{>[^<>]*</}{ $& =~ tr/ /_/r }eg'

Здесь [^<>] используется, чтобы убедиться, что соответствующая подстрока не может содержать < или > (в частности, она не может совпадать с другими тегами <phrase>).

Если это слишком читабельно, вы также можете сделать

perl '-pes;>[^<>]*</;$&=~y> >_>r;eg'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...