Сценарий оболочки для поиска, поиска и замены массива строк в файле - PullRequest
2 голосов
/ 10 июля 2010

Это связано с другим вопросом / кодом-гольфом, который я задал на Код-гольф: «Цветная подсветка» повторного текста

У меня есть файл 'sample1.txt' со следующим содержимым:

LoremIpsumissimplydummytextoftheprintingandtypesettingindustry.LoremIpsumhasbeentheindustry'sstandarddummytexteversincethe1500s,whenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbook.

У меня есть скрипт, генерирующий следующий массив строк, которые встречаются в файле (только несколько показаны для иллюстрации):

LoremIpsum
LoremIpsu
dummytext
oremIpsum
LoremIps
dummytex
industry
oremIpsu
remIpsum
ummytext
LoremIp
dummyte
emIpsum
industr
mmytext

Мне нужно (сверху) посмотреть, встречается ли LoremIpsum в файле sample1.txt. Если это так, я хочу заменить все вхождения LoremIpsum на: <T1>LoremIpsum</T1>. Теперь, когда программа переходит к следующему слову 'LoremIpsu', оно НЕ должно совпадать с текстом <T1>LoremIpsum</T1> внутри sample1.txt. Следует повторить вышеописанное для всех элементов этого «массива». Следующим «действительным» будет «dummytext», который должен быть помечен как <T2>dummytext</T2>.

Я думаю, что для этого должно быть возможно создать сценарий для оболочки bash, а не полагаться на программы на perl / python / ruby.

Ответы [ 2 ]

1 голос
/ 10 июля 2010

Pure Bash (без внешних элементов)

В командной строке Bash:

$ sample="LoremIpsumissimplydummytextoftheprintingandtypesettingindustry.LoremIpsumhasbeentheindustry'sstandarddummytexteversincethe1500s,whenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbook."
$ # or: sample=$(<sample1.txt)
$ array=(
LoremIpsum
LoremIpsu
dummytext
...
)
$ tag=0; for entry in ${array[@]}; do test="<[^>/]*>[^>]*$entry[^<]*</"; if [[ ! $sample =~ $test ]]; then ((tag++)); sample=${sample//${entry}/<T$tag>$entry</T$tag>}; fi; done; echo "Output:"; echo $sample
Output:
<T1>LoremIpsum</T1>issimply<T2>dummytext</T2>oftheprintingandtypesetting<T3>industry</T3>.<T1>LoremIpsum</T1>hasbeenthe<T3>industry</T3>'sstandard<T2>dummytext</T2>eversincethe1500s,whenanunknownprintertookagalleyoftypeandscrambledittomakeatypespecimenbook.
0 голосов
/ 12 июля 2010

Простой с Perl:

#! /usr/bin/perl

use warnings;
use strict;

my @words = qw/
  LoremIpsum
  LoremIpsu
  dummytext
  oremIpsum
  LoremIps
  dummytex
  industry
  oremIpsu
  remIpsum
  ummytext
  LoremIp
  dummyte
  emIpsum
  industr
  mmytext
/;

my $to_replace = qr/@{[ join "|" =>
                        sort { length $b <=> length $a }
                        @words
                     ]}/;

my $i = 0;
while (<>) {
  s|($to_replace)|++$i; "<T$i>$1</T$i>"|eg;
  print;
}

Пробный прогон (для предотвращения горизонтальной прокрутки):

$ ./tag-words sample.txt
<T1>LoremIpsum</T1>issimply<T2>dummytext</T2>oftheprintingandtypesetting<T3>indus
try</T3>.<T4>LoremIpsum</T4>hasbeenthe<T5>industry</T5>'sstandard<T6>dummytext</T
6>eversincethe1500s,whenanunknownprintertookagalleyoftypeandscrambledittomakeatyp
especimenbook.

Вы можете возразить, что вся бизнес qr// и @{[ ... ]}на стороне барокко.С переключателем регулярных выражений /o можно получить тот же эффект, что и в

# plain scalar rather than a compiled pattern
my $to_replace = join "|" =>
                 sort { length $b <=> length $a }
                 @words;

my $i = 0;
while (<>) {
  # o at the end for "compile (o)nce"
  s|($to_replace)|++$i; "<T$i>$1</T$i>"|ego;
  print;
}
...