Как заменить дублирующую строку на счетчик добавленных значений в нескольких файлах в командной строке Linux - PullRequest
0 голосов
/ 04 июня 2018

Как мы можем изменить существующие файлы, заменив строку "string" значениями, увеличенными счетчиком, следующим образом.

Примечание 1: Первый "string" пропускается. Примечание2 : Кроме того, «строка» не будет отображаться в одной строке более одного раза. Примечание 3 : строка foo "string" -> строка foo "string" 1bar правильна

File1 ("string" встречается внутри файла в любой строке)

some text
"string" here

File2 ("string" встречается трижды внутри файла в любой строке)

some text
"string" here
some more
text "string"
why "string"

File3 ("string" не встречается внутри файла в любой строке)

some text
why here
some more>
text pttn
why pttn

File4("string" встречается внутри файла в любой строке)

some "string"
no here

Как заменить "string" на "string"1 "string"2, "string"3 и т. Д.?

Ожидаемый результат:

Файл1

some text
"string" here

Файл2

some text
"string"1 here
some more
text "string"2
why "string"3

Файл3

some text
why here
some more
text pttn
why pttn

Файл4

some "string"4
no here

Ответы [ 5 ]

0 голосов
/ 12 июня 2018

Я просто подумал, что попробую.

Вот один вкладыш:

awk -v strVar='"string"' -v count=-1 '
   NR>1 { $0 ~ strVar && ++count && gsub(strVar, strVar count) }
1' file1 file2 file3 file4

Вы, по сути:

  1. инициализируйтеcounter, (-v count=-1)
  2. игнорировать первую строку ввода (NR>1)
  3. проверить, соответствует ли строка строке ($0 ~ strVar)
  4. , если это такувеличьте счетчик (&& ++count)
  5. , если увеличенный счетчик больше нуля (++count вернет 0 -> false для значения ноль и >0 -> true с тех пор, так что он работает как нужно какусловие для печати тоже)
    • начать замену строки увеличивающимся постфиксом (&& gsub(str, str count)
  6. напечатать результат ({}1)

Обратите внимание: если вы не возражаете против подсчета первой строки и / или знаете, что первая строка file1 не содержит "строку" , решение может бытьеще меньше / проще:

awk -v strVar='"string"' -v count=1 '
   { gsub(strVar, strVar count) && count++ }
1' file1 file2 file3 file4

, что означало бы, что для каждой замены вы увеличиваете счетчик, и выдает:

% awk -v strVar='"string"' -v count=1 '{ gsub(strVar, strVar count) && count++ }1' file1 file2 file3 file4

some text
"string"1 here

some text
"string"2 here
some more
text "string"3
why "string"4

some text
why here
some more
text pttn
why pttn

some "string"5
no here

С уважением

0 голосов
/ 08 июня 2018

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

sed -nr '/"string"/!b;x;/./!{s/^/0/;x;ba};:b;s/9(_*)$/_\1/;tb;s/^(_*)$/0\1/;s/$/\n0123456789/;s/(.)(_*)\n.*\1(.).*/\3\2/;y/_/0/;x;G;s/("string")(.*)\n(.*)/\1\3\2/;:a;W /dev/stdout' File? |
sed -i.bak -e '/"string"/!b;R /dev/stdin' -e 'd' File?

Создайте файл со всеми измененными строками, Обновите файлы по одному с измененными строками.

При первом вызове sed берется каждая строка, содержащая "string", и увеличивает ее (кроме первой) и выводит в stdout.

Второй вызов sed заменяет каждую строку, содержащую "string", следующей строкой из stdin.Файлы обновляются inline с помощью опции -i.bak, и это создает резервную копию исходного файла с суффиксом .bak.

NB. Предполагается, что в каждой строке есть только одно вхождение "string".

0 голосов
/ 04 июня 2018

не проверено

gawk -i inplace -v p="pattern" '
    {for (i=1; i<=NF; i++) if ($i == p) {$i = p n; n++}; print}
' File{1,2,3,4}
0 голосов
/ 07 июня 2018

Ваш вопрос все еще неясен, но это МОЖЕТ быть тем, что вы ищете:

$ awk -v str='"string"' '
    BEGIN { lgth = length(str) }
    pos=index($0,str) {
        $0 = substr($0,1,pos+lgth-1) cnt substr($0,pos+lgth)
        cnt++
    }
    1' file{1,2,3,4}
some text
"string" here
some text
"string"1 here
some more
text "string"2
why "string"3
some text
why here
some more
text pttn
why pttn
some "string"4
no here

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

0 голосов
/ 04 июня 2018

В случае, если вы хотите сохранить выходные данные в самих Input_file (s), вам могут помочь следующие.

gawk -i inplace -v INPLACE_SUFFIX=.bak -v val="-1" '/pattern/{val++} {val=val==0?"":val;sub(/pattern/,"&"val)} 1' File1 File2 File3 File4

Теперь добавлена ​​и форма решения не в один слой.

gawk -i inplace -v INPLACE_SUFFIX=.bak -v val="-1" '
/pattern/{
  val++}
{
  val=val==0?"":val;
  sub(/pattern/,"&"val)}
1' File1 File2 File3 File4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...