英文:
Tcl: How to get value from array when Myarray is a variable?
问题
I have many files that needed to be processed:
I'm using array names to get information in these, using proc like this:
proc array_proc {f} {
global f_name
set f_name [file tail $f]
set mtime [file mtime $f]
set date [clock format $mtime -format %D]
global $f_name
array set $f_name [list time $mtime]
}
set files [list /home/dir1/a.txt /home/dir2/b.txt]
foreach f {files} {
array_proc $f
puts "$f $f_name $$f_name(time) $$f_name(date)"
}
##I want my variables and output like this: (mtime and date is just random example here)
$f $f_name $$f_name(time) $$f_name(date)
/home/dir1/a.txt a.txt 4123123 03/07/2012
/home/dir2/b.txt b.txt 5123123 03/02/2011
The problem is, I want to have Myarray as a f_name variable because there are many files, so the data would be like: a.txt(time) a.txt(date) b.txt(time) b.txt(date)
, and it uses only the f_name variable in my foreach loop.
But I don't know how to substitute the f_name variable first so I could get the array value of that particular f_name array.
英文:
I have many files that needed to be processed:
I'm using array names to get information in these, using proc like this:
proc array_proc {f} {
global f_name
set f_name
set mtime
set date [clock format $mtime -format %D]
global $f_name
array set $f_name [list time $mtime]
}
set files [list /home/dir1/a.txt /home/dir2/b.txt]
foreach f {files} {
array_proc $f
puts "$f $f_name $$f_name(time) $$f_name(date)"
}
##I want my variables and output like this: (mtime and date is just random example here)
$f $f_name $$f_name(time) $$f_name(date)
/home/dir1/a.txt a.txt 4123123 03/07/2012
/home/dir2/b.txt b.txt 5123123 03/02/2011
The problem is, I want to have Myarray as a f_name variable, because there's many files, so the data would be like: a.txt(time) a.txt(date) b.txt(time) b.txt(date)
, and it use only the f_name variable in my foreach loop
But I don't know how to subsitute the f_name variable first so I could get the array value of that particular f_name array.
答案1
得分: 1
$$f_name(time)
Tcl doesn't do double substitution (without commands like `eval`).
Two ways to handle this dynamic array name:
1. use the `array get` command
```tcl
[array get $f_name time]
-
use the 1-argument
set
command (for which$
expansion is "syntactic sugar")[set [set f_name](time)]
But it's the dynamic variable name that is making this hard. A couple of ways around this as well
-
setting up this demo:
$ touch -t 202301010000 a.txt $ touch b.txt $ ls -l *.txt -rw-r--r-- 1 glennj glennj 0 Jan 1 00:00 a.txt -rw-r--r-- 1 glennj glennj 0 Mar 8 14:17 b.txt
-
Use just one array for the file metadata, putting the file tail as part of a compound key
proc array_proc_2 {f} { global file_info set fname [file tail $f] set mtime [file mtime $f] set file_info($fname,time) $mtime set file_info($fname,date) [clock format $mtime -format %D] } array_proc_2 ./a.txt array_proc_2 ./b.txt parray file_info puts "b date = $file_info(b.txt,date)"
file_info(a.txt,date) = 01/01/2023 file_info(a.txt,time) = 1672531200 file_info(b.txt,date) = 03/08/2023 file_info(b.txt,time) = 1678285064 b date = 03/08/2023
-
use a
dict
proc array_proc_3 {f} { global file_stats set fname [file tail $f] set mtime [file mtime $f] dict set file_stats $fname time $mtime dict set file_stats $fname date [clock format $mtime -format %D] } array_proc_3 ./a.txt array_proc_3 ./b.txt puts $file_stats puts "b date = [dict get $file_stats b.txt date]"
a.txt {time 1672531200 date 01/01/2023} b.txt {time 1678285064 date 03/08/2023} b date = 03/08/2023
<details>
<summary>英文:</summary>
`$$f_name(time)`
Tcl doesn't do double substitution (without commands like `eval`).
Two ways to handle this dynamic array name:
1. use the `array get` command
```tcl
[array get $f_name time]
-
use the 1-argument
set
command (for which$
expansion is "syntactic sugar")[set [set f_name](time)]
But it's the dynamic variable name that is making this hard. A couple of ways around this as well
-
setting up this demo:
$ touch -t 202301010000 a.txt $ touch b.txt $ ls -l *.txt -rw-r--r-- 1 glennj glennj 0 Jan 1 00:00 a.txt -rw-r--r-- 1 glennj glennj 0 Mar 8 14:17 b.txt
-
Use just one array for the file metadata, putting the file tail as part of a compound key
proc array_proc_2 {f} { global file_info set fname [file tail $f] set mtime [file mtime $f] set file_info($fname,time) $mtime set file_info($fname,date) [clock format $mtime -format %D] } array_proc_2 ./a.txt array_proc_2 ./b.txt parray file_info puts "b date = $file_info(b.txt,date)"
file_info(a.txt,date) = 01/01/2023 file_info(a.txt,time) = 1672531200 file_info(b.txt,date) = 03/08/2023 file_info(b.txt,time) = 1678285064 b date = 03/08/2023
-
use a
dict
proc array_proc_3 {f} { global file_stats set fname [file tail $f] set mtime [file mtime $f] dict set file_stats $fname time $mtime dict set file_stats $fname date [clock format $mtime -format %D] } array_proc_3 ./a.txt array_proc_3 ./b.txt puts $file_stats puts "b date = [dict get $file_stats b.txt date]"
a.txt {time 1672531200 date 01/01/2023} b.txt {time 1678285064 date 03/08/2023} b date = 03/08/2023
答案2
得分: 0
您可以使用tcl命令"upvar"。默认情况下,tcl过程是按值调用的。使用upvar,您可以获取传递给过程的变量名。请参考以下示例:
proc array_proc { varName } {
upvar $varName var
set v1 $var(date) ;# 获取一个元素
set var(time) [expr {$v1 + 100}] ;# 设置一个元素
}
set a(date) 34
set b(date) 56
array_proc a
array_proc b
parray a
parray b
exit
输出:
a(date) = 34
a(time) = 134
b(date) = 56
b(time) = 156
英文:
You may use tcl command "upvar". By default, tcl procedure is called by value. With upvar, You can get the variable name passed to a procedure. See the following example:
<!-- language: lang-tcl -->
proc array_proc { varName } {
upvar $varName var
set v1 $var(date) ;# Get an element
set var(time) [expr {$v1 + 100}] ;# Set an element
}
set a(date) 34
set b(date) 56
array_proc a
array_proc b
parray a
parray b
exit
# Output:
# a(date) = 34
# a(time) = 134
# b(date) = 56
# b(time) = 156
答案3
得分: 0
经过阅读Glenn和Donal的答案后,我考虑重新格式化我的数据,将数组和字典组合成类似以下的结构:
proc file_info_proc {f} {
global file_info
set f_name [file tail $f]
set mtime [file mtime $f]
set date [clock format $mtime -format %D]
set file_info($f) "
f_name $f_name
mtime $mtime
date $date
"
}
set file_a /home/dir1/a.txt
file_info_proc $file_a
file_info_proc ./b.txt
puts "$file_a [dict get $file_info($file_a) f_name] [dict get $file_info($file_a) date]"
puts $file_info
/home/dir1/a.txt a.txt 03/07/2023
/home/dir1/a.txt {
f_name a.txt
mtime 1678162276
date 03/07/2023
} ./b.txt {
f_name b.txt
mtime 1677036509
date 02/22/2023
}
file_info数组将存储文件,并替代数组变量将给我一个字典,我可以轻松地在我的过程中配置。非常感谢帮助。
英文:
After reading Glenn and Donal answers, I'm thinking about reformatting my data again, combining the array and dict for something like this:
proc file_info_proc {f} {
global file_info
set f_name
set mtime
set date [clock format $mtime -format %D]
set file_info($f) "
f_name $f_name
mtime $mtime
date $date
"
}
set file_a /home/dir1/a.txt
file_info_proc $file_a
file_info_proc ./b.txt
puts "$file_a [dict get $file_info($file_a) f_name] [dict get $file_info($file_a) date]"
puts $file_info
/home/dir1/a.txt a.txt 03/07/2023
/home/dir1/a.txt {
f_name a.txt
mtime 1678162276
date 03/07/2023
} ./b.txt {
f_name b.txt
mtime 1677036509
date 02/22/2023
}
The file_info array will store the files, and subsitute the array variable will get me a dict, which I can easily config inside my proc.
Thanks a lot for the help.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论