替换C文件行的TCL脚本
我有一个C文件 C:\SVN\Code\fileio.C 这会将2个音频文件读取为替换C文件行的TCL脚本,tcl,Tcl,我有一个C文件 C:\SVN\Code\fileio.C 这会将2个音频文件读取为 tuningFile = fopen("../../simulation/micdata.bin", "rb"); mic1File = fopen("../../simulation/mic1.pcm", "rb"); 我需要编写TCL脚本代码来读取C文件,并将这两个实例替换为 tuningFile = fopen("C:/SVN/simulation/micdata.bin", "rb");
tuningFile = fopen("../../simulation/micdata.bin", "rb");
mic1File = fopen("../../simulation/mic1.pcm", "rb");
我需要编写TCL脚本代码来读取C文件,并将这两个实例替换为
tuningFile = fopen("C:/SVN/simulation/micdata.bin", "rb");
mic1File = fopen("C:/SVN/simulation/mic1.pcm", "rb");
任何人都可以举一个简单的例子来说明以下内容:
- 逐行读取文件
- 搜索类似tuningFile=fopen的内容(
- 从中提取路径并将其更改为绝对路径
- 将其与*tuningFile=fopen(
- 在同一位置用修改后的行替换原始行
sedy关键是您实际上想要替换:
fopen("../../simulation/
与
使用字符串映射
很容易做到这一点。接下来的问题只是执行文件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]
获取文件名作为参数。代码的其余部分并不重要。关键是您实际上想要替换:
fopen("../../simulation/
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]
与
使用字符串映射
很容易做到这一点。接下来的问题只是执行文件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]
将文件名作为参数获取。代码的其余部分不在乎
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中删除了映射的定义)。updateInPlace
在其第二个参数中调用命令前缀,将文件的内容传递给该命令,并使用命令的结果更新文件
这与Donal的回答中的步骤非常接近,用更高级别的代码表示。如果需要备份副本,请在调用updateInPlace
之前执行此操作:
file copy $filename [file rootname $filename].bak
文件:文件包
应该也可以。(从Donal中删除了映射的定义)。updateInPlace
在其第二个参数中调用命令前缀,将文件的内容传递给该命令,并使用命令的结果更新文件
这与Donal的回答中的步骤非常接近,用更高级别的代码表示。如果需要备份副本,请在调用updateInPlace
之前执行此操作:
file copy $filename [file rootname $filename].bak
文档:包,这是一个提取文件名并在其上使用文件规范化的版本:
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"]}]]
打破这种局面
此命令
regsub -all {((?:tuningFile|mic1File) = fopen\(")([^"]+)} $code {\1[file normalize "\2"]}
将找到字符串tuningFile=fopen(../relative/file
(或“mic1file=…”),并将其替换为文本
tuningFile = fopen("[file normalize "../relative/file"]
然后我们将其馈送到subst
,以便可以替换嵌入的命令,执行文件规范化
命令,生成文本
tuningFile = fopen("/full/path/to/file
第2步:在C代码中处理括号
$ 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");
以下是一个提取文件名并在其上使用文件规范化的版本:
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"]}]]
打破这种局面
此命令
regsub -all {((?:tuningFile|mic1File) = fopen\(")([^"]+)} $code {\1[file normalize "\2"]}
将找到字符串tuningFile=fopen(../relative/file
(或“mic1file=…”),并将其替换为文本
tuningFile = fopen("[file normalize "../relative/file"]
然后我们将其馈送到subst
,以便可以替换嵌入的命令,执行文件规范化
命令,生成文本
tuningFile = fopen("/full/path/to/file
第2步:在C代码中处理括号
$ 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");
基于所有发表评论的用户的巨大帮助,我能够按要求完成任务
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
基于所有发表评论的用户的巨大帮助,我能够按要求完成任务
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
您最好创建一个带有更正的临时文件,并将实际文件替换为临时文件。我不能这样做。TCL脚本传递了一个参数,该参数决定是保留绝对路径还是相对路径。因此,我需要一种以编程方式更改它的方法。您最好创建一个带有更正的临时文件,并替换实际的fi我不能这样做。TCL脚本被传递了一个参数,该参数决定是保留绝对路径还是相对路径。因此,我需要一种以编程方式对其进行更改的方法。我欣赏这种响应。但是,从相对路径到绝对路径的映射本身并不是固定的。因此,如果脚本在不同的计算机上运行,“../../simulation/可能会转换为其他内容,而不是“C:/SVN/simulation”。因此,我需要使用[file normalize$origfile],以便在使用相对路径读取该行后,它将用通过[file normalize$origfile]获得的绝对路径替换它。我很感谢您的响应。但是,从相对路径到绝对路径的映射本身并不是固定的。因此,如果脚本在不同的计算机上运行,“../../simulation/可能会转换为其他内容,而不是“C:/SVN/simulation”。因此,我需要[file normalize$origfile]要使用它,一旦用相对路径读取了行,它就会用通过[file normalize$origfile]获得的绝对路径来替换它。这本质上就是perls/pattern/some code here/e
Hi-Glenn的Tcl惯用用法,因为C代码的数组定义为int-tuningFix[MAXTUNING];解释器在从$code读取时将其视为命令并进行投诉。添加了处理代码中方括号的更新版本这本质上是perls/pattern/some code here/e的Tcl惯用用法。嗨,Glenn,regsub命令对我来说失败,因为C代码的数组定义为int tuningFix[MAXTUNING];当从$code读取时,解释器将其视为命令并进行投诉。添加了处理代码中括号的更新版本