Tcl: 如何在Myarray是一个变量时从数组中获取值?

huangapple go评论78阅读模式
英文:

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]
  1. 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
    
  1. 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
    
  2. 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&#39;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]
  1. 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
    
  1. 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 &quot;b date = $file_info(b.txt,date)&quot;
    
    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
    
  2. 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 &quot;b date = [dict get $file_stats b.txt date]&quot;
    
    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) &quot;
        f_name  $f_name
        mtime   $mtime
        date    $date
    &quot; 
}

set file_a /home/dir1/a.txt
file_info_proc $file_a
file_info_proc ./b.txt

puts &quot;$file_a [dict get $file_info($file_a) f_name] [dict get $file_info($file_a) date]&quot;
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.

huangapple
  • 本文由 发表于 2023年3月8日 15:05:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670172.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定