Найдите конкретную строку из текстового файла, используя два шаблона, затем замените переменную строку в этой строке

#shell #awk #sed

#оболочка #awk #sed

Вопрос:

У меня есть большой текстовый файл (myfile.txt ), где ровно для одной строки я пытаюсь заменить значение «0.999999999» другим числом, скажем, «0.111111111».

 expression "if((CONDITION1==1),0.999999999,CATEGORY1)"
 

Строка может быть однозначно идентифицирована путем поиска как строки перед ней, так и за ней (должны быть оба вместе, иначе шаблон не уникален), или в этом случае

 'expression "if((CONDITION1==1),'
and
',CATEGORY1)"'
 

После изучения нескольких других сообщений я нахожу, что сложная часть в моем случае заключается в

  1. определите конкретную строку по нескольким шаблонам и
  2. замена строки, по которой невозможно выполнить поиск сам по себе (поскольку она может измениться)

Первая проблема, которую я вижу, была решена в других сообщениях, но я в тупике по второму.

Я пробовал несколько разных способов, но ни один из них не дает правильных результатов, ближайший, который я получил, это :

 sed -n '/if((CONDITION1==1).CATEGORY1)/{ s/,*,/,0.111111111,/p }' myfile.txt

 

Где я пытаюсь идентифицировать строки, просматривая часть строк префикса и суффикса, а затем пытаясь заменить все между и включая две запятые.

Мои вопросы:

  1. что я делаю не так?
  2. является ли sed лучшим инструментом для этой задачи, или awk или perl справятся лучше? Спасибо.

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

Я обновил свой код на основе версии @Ed, чтобы иметь возможность считывать значение из переменной, извлеченной из этого файла, во время выполнения кода на основе ввода. Надеюсь, это поможет кому-нибудь позже:

 #test.sh
month= $1
VAL= $(cat data_$month.dat | awk 'NR==2') 
echo "VAL is:" $VAL
sed -i 's/(expression "if((CONDITION1==1),)[^,]*(,CATEGORY1)")/1'"${VAL}"'2/' file
 

Ответ №1:

 $ sed 's/(expression "if((CONDITION1==1),)[^,]*(,CATEGORY1)")/10.1111111112/' file
expression "if((CONDITION1==1),0.111111111,CATEGORY1)"
 

Вот пример того, почему часть, которую вы не записываете, должна быть [^,]* вместо .* :

 $ cat file
expression "if((CONDITION1==1),0.999999999,CATEGORY1)"  # this is ",CATEGORY1)"
expression "if((CONDITION1==1),0.999999999,FOO)"        # this is not ",CATEGORY1)"

$ sed 's/(expression "if((CONDITION1==1),)[^,]*(,CATEGORY1)")/10.1111111112/' file
expression "if((CONDITION1==1),0.111111111,CATEGORY1)"  # this is ",CATEGORY1)"
expression "if((CONDITION1==1),0.999999999,FOO)"        # this is not ",CATEGORY1)"

$ sed 's/(expression "if((CONDITION1==1),).*(,CATEGORY1)")/10.1111111112/' file
expression "if((CONDITION1==1),0.111111111,CATEGORY1)"
expression "if((CONDITION1==1),0.111111111,CATEGORY1)"
 

Комментарии:

1. Спасибо, Эд. Ваш код делает именно то, что я искал

Ответ №2:

если ваши данные в файле ‘d’, попробуйте gnu sed:

 sed -E 'h;s/expression "if((CONDITION1==1),([0-9.] ),CATEGORY1)"/1/;s/9/1/g;G;s/(. )n([^,] ,)[^,] (,. )/213/' d