Как бороться с sed в Tcl скрипте с подстановкой - PullRequest
0 голосов
/ 20 сентября 2018

Я пишу сценарий Tcl, который вставляет некоторый текст в файл за соответствующей строкой.Ниже приведены основные коды в скрипте.

set test_lists [list "test_1"\
                 "test_2"\
                 "test_3"\
                 "test_4"\
                 "test_5"
                ]

foreach test $test_lists {
    set content "
    'some_data/$test'
    "
    exec sed -i "/dog/a$content" /Users/l/Documents/Codes/TCL/file.txt
}

Однако, когда я запускаю этот скрипт, он всегда показывает мне эту ошибку:

dyn-078192:TCL l$ tclsh test.tcl 

sed: -e expression #1, char 12: unknown command: `''
    while executing
"exec sed -i "/dog/a$content" /Users/l/Documents/Codes/TCL/file.txt"
    ("foreach" body line 5)
    invoked from within
"foreach test $test_lists {
    set content "
    'some_data/$test'
    "
    exec sed -i "/dog/a$content" /Users/l/Documents/Codes/TCL/file.txt
}"
    (file "test.tcl" line 8)

Каким-то образом он всегда пытался оценитьпервое слово в $content как команда.

Есть идеи, что мне следует сделать, чтобы сделать эту работу?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

(расширенный комментарий, а не ответ)

Запуск этого в оболочке для уточнения желаемого результата: это то, что вы хотите?

$ cat file.txt
foo
dog A
dog B
dog C
dog D
dog E
bar

$ for test in test_{1..5}; do content="some_data/$test"; sed -i "/dog/a$content" file.txt; done

$ cat file.txt
foo
dog A
some_data/test_5
some_data/test_4
some_data/test_3
some_data/test_2
some_data/test_1
dog B
some_data/test_5
some_data/test_4
some_data/test_3
some_data/test_2
some_data/test_1
dog C
some_data/test_5
some_data/test_4
some_data/test_3
some_data/test_2
some_data/test_1
dog D
some_data/test_5
some_data/test_4
some_data/test_3
some_data/test_2
some_data/test_1
dog E
some_data/test_5
some_data/test_4
some_data/test_3
some_data/test_2
some_data/test_1
bar
0 голосов
/ 20 сентября 2018

Сначала вы должны решить точно , какие символы нужно обработать с помощью sed.(См. https://unix.stackexchange.com/questions/445531/how-to-chain-sed-append-commands, почему это может иметь значение…) Они могут быть:

/dog/a\
'some_data/test_1'

, что превращает файл вроде:

abc
dog
hij

в

abc
dog
'some_data/test_1'
hij

Если это то, что вам нужно, вы можете перейти ко второму этапу: получить этих персонажей из Tcl в sed.

# NB: *no* newline here!
set content "'some_data/$test'"

# NB: there's a quoted backslashes and two quoted newlines here
exec sed -i "/dog/a\\\n$content\n" /Users/l/Documents/Codes/TCL/file.txt

Одно из немногих мест, где вам следует соблюдать осторожность при цитированиив Tcl, когда у вас есть обратная косая черта и новые строки в непосредственной близости.


Почему бы не выполнить преобразование текста непосредственно в самом Tcl?Это может изменить порядок вставленных строк по сравнению с исходным кодом.Вы можете исправить это, lreverse составив список в удобное время, и, возможно, вам также понадобится дополнительная обработка текста для вставки.Вот и все уточнения ...

set test_lists [list "'some_data/test_1'"\
             "'some_data/test_2'"\
             "'some_data/test_3'"\
             "'some_data/test_4'"\
             "'some_data/test_5'"
            ]

set filename /Users/l/Documents/Codes/TCL/file.txt
set REGEXP "dog"

# Read in the data; this is good even for pretty large files
set f [open $filename]
set lines [split [read $f] "\n"]
close $f

# Search for first matching line by regular expression
set idx [lsearch -regexp $lines $REGEXP]
if {$idx >= 0} {
    # Found something, so do the insert in the list of lines
    set lines [linsert $lines [expr {$idx + 1}] {*}$test_lists]

    # Write back to the file as we've made changes
    set f [open $filename "w"]
    puts -nonewline $f [join $lines "\n"]
    close $f
}
...