Замена строки с помощью sed в скрипте tcl - строка содержит круглые скобки

Я хочу использовать sed в сценарии tcl для изменения файла (хранящегося в $file), который содержит строку:

prbs_match_out ‹= (ch0_prbs_match_dual3_int & ch0_prbs_match_dual2_int & ch0_prbs_match_dual1_int & ch0_prbs_match_int) & ( ch1_prbs_match_dual3_int & ch1_prbs_match_dual2_int & ch1_prbs_match_dual1_int & ch1_prbs_match_int);

to

prbs_match_out ‹= ch0_prbs_match_int & ch1_prbs_match_int;

Пытаться:

exec /bin/sed -i {s/(ch0_prbs_match_dual3_int  &  ch0_prbs_match_dual2_int  &  ch0_prbs_match_dual1_int  &  ch0_prbs_match_int) & (   ch1_prbs_match_dual3_int  &  ch1_prbs_match_dual2_int  &  ch1_prbs_match_dual1_int  &  ch1_prbs_match_int)/ch0_prbs_match_int & ch1_prbs_match_int/g}  $file

Приведенная выше команда sed не работает (получается неверная замена). Как обрабатывать круглые скобки и амперсанды в sed?


person LokSas    schedule 03.04.2019    source источник
comment
можете ли вы упростить свою проблему, заменив любую строку, начинающуюся с prbs_match_out <= на prbs_match_out <= ch0_prbs_match_int & ch1_prbs_match_int;, или большая строка, которую вы включили, действительно единственная версия prbs_match_out <=, которую вам нужно исправить? Также прочитайте grymoire.com/Unix/Sed.html. Удачи.   -  person shellter    schedule 03.04.2019
comment
Я хочу исправить только строку (уникальную) prbs_match_out <= (ch0_prbs_match_dual3_int & ch0_prbs_match_dual2_int & ch0_prbs_match_dual1_int & ch0_prbs_match_int) & ( ch1_prbs_match_dual3_int & ch1_prbs_match_dual2_int & ch1_prbs_match_dual1_int & ch1_prbs_match_int);   -  person LokSas    schedule 03.04.2019
comment
Также обратите внимание, что sed не может легко сопоставлять шаблоны, которые растягиваются на несколько строк текста. В ваших примерах данных неясно, является ли это одной непрерывной строкой текста или отформатировано в несколько строк. Вам нужно экранировать скобки и & символы, так как они имеют особое значение для sed регулярных выражений. Итак (возможно) s/\(ch0_prbs_match_dual3_int \& ....\) ... В зависимости от версии sed, которую вы используете, и любых параметров, которые вы включили, вам может не понадобиться экранировать скобки. Лучше всего сначала получить небольшой образец, а затем попробовать его на полной линии. Удачи.   -  person shellter    schedule 03.04.2019
comment
В BRE sed скобки и амперсанд не имеют особого значения. & имеет особое значение в части замены команды s. Если вы запускаете sed с sed -r или sed -E, то вы используете ERE, и круглые скобки становятся особыми в шаблоне.   -  person glenn jackman    schedule 03.04.2019
comment
@LokSas, форматирование вашего вопроса затрудняет его воспроизведение. Содержит ли ваш ввод новые строки? Являются ли несколько пробелов значительными или нет?   -  person glenn jackman    schedule 03.04.2019


Ответы (4)


Рассматривали ли вы возможность использования Tcl для этого преобразования на месте, например. с помощью его команды [regsub]:

set x [regsub {(\([^)]*\))} $x ch0_prbs_match_int]
set x [regsub {(\([^)]*\))} $x ch1_prbs_match_int]

исправить только строку (уникальную)

Это предполагает, что переменная x содержит содержимое вашего файла и что заменяемые элементы строки можно однозначно идентифицировать, отслеживая совпадающие пары круглых скобок.

person mrcalvin    schedule 03.04.2019

Если у вас есть файл content (или строка файла) в переменной, вы можете использовать string map для замены одной подстроки другим текстом.

person glenn jackman    schedule 03.04.2019

Я понял - сработала команда tcl "string map". Спасибо за вашу помощь.

package require Tcl 8.5

package require fileutil

# Parameters for the replacement 
set from "(   ch0_prbs_match_dual3_int  &  ch0_prbs_match_dual2_int  &  ch0_prbs_match_dual1_int  &  ch0_prbs_match_int) & (   ch1_prbs_match_dual3_int  &  ch1_prbs_match_dual2_int  &  ch1_prbs_match_dual1_int  &  ch1_prbs_match_int)"
set to "ch0_prbs_match_int & ch1_prbs_match_int"

# Which file to replace 
set checkingFile /proj/dada/test.v

# Make a command fragment that performs the replacement on a supplied string
set replacementCmd [list string map [list $from $to]]

# For single file replacement 
fileutil::updateInPlace $checkingFile $replacementCmd
person LokSas    schedule 03.04.2019

В BRE (базовом регулярном выражении) только шесть символов должны быть экранированы для буквальной обработки: ^$.*\[.
Кроме того, вам нужно экранировать & в части REPLACEMENT команды s в sed, потому что & имеет особое значение. совпадающей части в PATTERN.
В результате вы можете сказать что-то вроде:

#!/usr/bin/tclsh

set file {yourfilename}
exec /bin/sed -i {s/(ch0_prbs_match_dual3_int & ch0_prbs_match_dual2_int & ch0_prbs_match_dual1_int & ch0_prbs_match_int) & ( ch1_prbs_match_dual3_int & ch1_prbs_match_dual2_int & ch1_prbs_match_dual1_int & ch1_prbs_match_int);/ch0_prbs_match_int \& ch1_prbs_match_int;/} $file

который изменяет $file как:

prbs_match_out <= ch0_prbs_match_int & ch1_prbs_match_int;
person tshiono    schedule 03.04.2019
comment
Вы не можете сказать именно это... потому что это классическая проблема с одинарными кавычками при вызове команды оболочки (обратите внимание на тег tcl). Я ответил на него недавно, поэтому я не хочу отвечать на него снова какое-то время… - person Donal Fellows; 03.04.2019
comment
Я ценю ваш совет. Буду иметь в виду :-). - person tshiono; 03.04.2019
comment
@DonalFellows Оказывается, команда sed работает, просто изменяя кавычки с одинарных кавычек на фигурные скобки, чтобы ее можно было выполнить из tcl. - person tshiono; 03.04.2019
comment
Спасибо за ваш ответ и объяснение, но это не сработало :( - person LokSas; 03.04.2019
comment
@LokSas Не могли бы вы уточнить, как это не работает (например, вывод, сообщение об ошибке и т. д.), включая вашу версию sed и tcl? Я тестировал с помощью sed (GNU sed) 4.2.2 и tclsh 8.6. Если вы решили проблему с ответами других, вам все равно не нужно тратить время на ответ на этот комментарий. БР. - person tshiono; 04.04.2019