Заменить часть строки другим текстом из другого файла строка за строкой - PullRequest
0 голосов
/ 01 февраля 2019

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

Это то, что у меня есть:

cat mock.txt | sed -i -e '/mock/{R/dev/stdin' -e 'd;}' test{1..500}.txt

Я хочу заменитьчасть строк, соответствующая шаблону из строк по порядку из другого файла, у меня до 500 текстовых файлов со структурой:

test1.txt, test2.txt, test3.txt ...

11111
22222
333= mock 33
55555
77777


и, таким образом, я читаю файл один за другим и заменяю в первом образце файла test1.txt первую строку из файла mock.txt во втором test2.txt заменяет строку шаблона макета второй строкой из файла mock.txt, структура которого выглядит следующим образом:

mock.txt

randomText1
randomText2
randomText3
randomText4
randomText5


и так до последнего файла .txt в папке

Ответы [ 4 ]

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

Вы не можете сделать это, используя sed за один шаг.

С info sed

'R filename'
     Queue a line of FILENAME to be read and inserted into the output
     stream at the end of the current cycle, or when the next input line
     is read.

Итак, для этого у вас есть второй проход :

cd /tmp
seq -f first-%03g 1 20 | tee test-{1..30}.txt >/dev/null 
seq -f newline-%04g 44 244 | sed -i -e '/first-004/R/dev/stdin' test-{1..30}.txt
sed -e '/first-004/{N;s/^\(.*\)rst-00\(.*\)\n\(.*\)/\1\3\2/}' -i test-{1..30}.txt

Затем

head -6 test-6.txt
first-001
first-002
first-003
finewline-00494
first-005
first-006

Где rst-00 заменяется на newline-0049 в строке, где изначально было first-004.

Оттуда, в соответствии с вашим запросом, но не проверено:

есть два прохода:

sed -e '/mock/R/dev/stdin' -i test{1..500}.txt <mock.txt
sed -e '/mock/{N;s/^\(.*\)mock\(.*\)\n\(.*\)$/\1\3\2/}' -i test{1..500}.txt
0 голосов
/ 01 февраля 2019

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

sed -i -e '/mock/R mockFile' -e '//d' file ...

NB Файл макета назван в сценарии sed, а не как ввод через stdin.Это позволяет sed сбрасывать mockFile для каждого входного файла.

Это заменит все экземпляры mock на строку из файла макета последовательно.Однако, если вы хотите связать все экземпляры макета в каждом файле с его позицией в файле макета, т.е. все экземпляры макета в файле file1 со строкой 1 файла макета и т. Д., Используйте:

parallel sed -i '/mock/c\{1}' {2} :::: mockFile :::+ file{1..500}.txt
0 голосов
/ 01 февраля 2019

РЕДАКТИРОВАТЬ: Так как OP говорит, что каждый раз для замены файла следует начинать с самого первого появления ложной строки из ложного файла, поэтому публикация следует сейчас.

awk '
FNR==NR{
  a[FNR]=$0
  next
}
prev!=FILENAME{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}
FNR==1{
  prev=FILENAME
  count=""
}
/mock/{
  $0=a[++count]
}
{
  print > "temp"
}
END{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}' mock.txt test[0-9].txt


Не могли бы вы попробовать следующее.В кратком объяснении (добавим полное объяснение) это изменит значение макета строки в соответствии со значением файла mock.text.Я добавил комментарий, чтобы спросить OP о том, может ли файл иметь более одного экземпляра, обновлю его в соответствии с ответом OP.

awk '
FNR==NR{
  a[FNR]=$0
  next
}
prev!=FILENAME{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}
FNR==1{
  prev=FILENAME
}
/mock/{
  $0=a[++count]
}
{
  print > "temp"
}
END{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}' mock.txt test[0-9].txt
0 голосов
/ 01 февраля 2019

Извините за предыдущую ошибку, пожалуйста, попробуйте снова ниже.
С GNU awk v4.1.0 + (пожалуйста, сначала сделайте резервную копию ваших файлов):

awk -i inplace 'NR==FNR{re[FNR]=$0;print;next}match(FILENAME,/test([0-9]+)/, fi){gsub("mock",re[fi[1]])}1' mock.txt test{1..500}.txt

Обратите внимание, что файлы не могут иметь возврат каретки \r\nокончания, если они есть, пожалуйста, прокомментируйте.

Если файлы содержат много строк, то для эффективности и поместить его в несколько строк для удобства чтения:

awk -i inplace '
    NR==FNR{re[FNR]=$0;print;next}
    FNR==1{match(FILENAME,/test([0-9]+)/, fi)}
    /mock/{gsub(/mock/,re[fi[1]])}
    1' mock.txt test{1..500}.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...