TCL脚本替换C文件行

时间:2015-09-03 00:35:22

标签: tcl

我有

的C档
  

C:\ SVN \代码\ fileio.c

这将读取2个音频文件

tuningFile = fopen("../../simulation/micdata.bin", "rb");   
mic1File = fopen("../../simulation/mic1.pcm", "rb");

我需要编写将读取C文件的TCL脚本代码,并将这两种情况替换为

tuningFile = fopen("C:/SVN/simulation/micdata.bin", "rb");    
mic1File = fopen("C:/SVN/simulation/mic1.pcm", "rb");

任何人都可以为下面的内容提供一个紧凑的例子:

  • 明确阅读文件
  • 搜索 tuningFile = fopen(
  • )之类的内容
  • 从中提取路径并将其更改为绝对路径
  • 将它与* tuningFile = fopen(
  • 使用相同位置的修改行替换原始行

感谢
sedy

4 个答案:

答案 0 :(得分:2)

关键是你真的要替换:

fopen("../../simulation/

fopen("C:/SVN/simulation/

使用string map轻松完成。其余的问题只是执行文件I / O,而且几乎可以由普通编译器编译的任何 C源文件最好通过将它们全部加载到内存来处理一旦:

set filename {C:\SVN\Code\fileio.c}
set mapping [list {fopen("../../simulation/} {fopen("C:/SVN/simulation/}]

# Slurp the file in
set f [open $filename]
set data [read $f]
close $f

# Apply the mapping
set data [string map $mapping $data]

# Make the original a backup
file rename $filename $filename.bak

# Write back with a separate open
set f [open $filename w]
puts -nonewline $f $data
close $f

如果您愿意,可以使用[lindex $argv 0]获取文件名作为参数。其余的代码并不关心。

答案 1 :(得分:1)

package require fileutil

set filename C:/SVN/Code/fileio.c
set mapping [list {fopen("../../simulation/} {fopen("C:/SVN/simulation/}]

proc replace {mapping data} {
    string map $mapping $data
}

::fileutil::updateInPlace $filename [list replace $mapping]

也应该工作。 (来自Donal的mapping的定义。)updateInPlace在其第二个参数中调用命令前缀,将文件的内容传递给该命令,并使用命令的结果更新文件。

这与Donal的答案几乎相同,用更高级别的代码表示。如果您需要备份副本,请在致电updateInPlace之前执行此操作:

file copy $filename [file rootname $filename].bak

文档:fileutil包,listprocsetstring

答案 2 :(得分:1)

这是一个提取文件名并在其上使用file normalize的版本:

set f [open $filename r]
set code [read $f]
close $f

set code [subst -novar -noback [regsub -all {((?:tuningFile|mic1File) = fopen\(")([^"]+)} $code {\1[file normalize "\2"]}]]

打破它,

  1. 此命令

    regsub -all {((?:tuningFile|mic1File) = fopen\(")([^"]+)} $code {\1[file normalize "\2"]}
    

    将找到字符串tuningFile = fopen("../relative/file(或“mic1file = ...”)并将其替换为文本

    tuningFile = fopen("[file normalize "../relative/file"]
    
  2. 然后我们将其提供给subst,以便替换嵌入式命令,执行file normalize命令,从而生成文本

    tuningFile = fopen("/full/path/to/file
    
  3. 在C代码中取2:句柄括号

    $ pwd
    /home/jackman/tmp/base/SVN/Code
    
    $ tree ../..
    ../..
    ├── SVN
    │   └── Code
    │       ├── fileio.c
    │       └── normalize.tcl
    └── simulation
        ├── mic1.pcm
        └── micdata.bin
    
    3 directories, 4 files
    
    $ cat fileio.c 
    int tuningFix[MAXTUNING];
    tuningFile = fopen("../../simulation/micdata.bin", "rb");   
    mic1File = fopen("../../simulation/mic1.pcm", "rb");
    
    $ cat normalize.tcl 
    #! tclsh
    package require fileutil
    set code [fileutil::cat [lindex $argv 0]]
    
    # protect existing brackets
    set bracketmap [list \[ \x01 \] \x02]
    set code [string map $bracketmap $code]
    
    # normalize filenames
    set code [
        subst -novar -noback [
            regsub -all {((?:tuningFile|mic1File) = fopen\(")([^"]+)} $code {\1[file normalize "\2"]} 
        ]
    ]
    
    # restore brackets
    set code [string map [lreverse $bracketmap] $code]
    
    puts $code
    
    $ tclsh normalize.tcl fileio.c 
    int tuningFix[MAXTUNING];
    tuningFile = fopen("/home/jackman/tmp/base/simulation/micdata.bin", "rb");   
    mic1File = fopen("/home/jackman/tmp/base/simulation/mic1.pcm", "rb");
    

答案 3 :(得分:0)

基于所有评论用户的大力帮助,我能够完成任务

proc replaceFileTemp {} {
    global pth_fileio_orig

    # create backup for copy back
    set pth_backup [file rootname $pth_fileio_orig].bak
    file copy $pth_fileio_orig $pth_backup

    #get current file path
    set thisFilePth [ dict get [ info frame [ info frame ] ] file ]

    # get folder for current file
    set thisFileFolderPth [file dirname $thisFilePth]

    # set the replacement string/path
    set replacementPth [file dirname $thisFileFolderPth]


    # obtain original string to be replaced 
    set origPth "../../simulation/toplevel"

    # download package for file manipulation
    package require fileutil


    set mapping [list $origPth $replacementPth]
    proc replace {mapping data} {
    string map $mapping $data
    }

    # replace original string with replacement string for all occurrences in file
    ::fileutil::updateInPlace $pth_fileio_orig [list replace $mapping]
}

# set the path to toplevel C file
set pth_fileio_orig [file normalize "../../../fileio.c"]
replaceFileTemp