在 awk 中使用 bc
Using bc in awk
我正在尝试在 awk 脚本中使用 bc。在下面的代码中,我试图将十六进制数转换为二进制数并将其存储在一个变量中。
#!/bin/awk -f
{
binary_vector = $(bc <<< "ibase=16;obase=2;FF")
}
我哪里出错了?
不是说这是个好主意但是:
$ awk 'BEGIN {
cmd = "bc <<< \"ibase=16;obase=2;FF\""
rslt = ((cmd | getline line) > 0 ? line : -1)
close(cmd)
print rslt
}'
11111111
另见 http://gnu.org/software/gawk/manual/gawk.html#Bitwise-Functions and http://gnu.org/software/gawk/manual/gawk.html#Nondecimal-Data
下面的一行 Awk 脚本应该做你想做的事:
awk -vVAR=$(read -p "Enter number: " -u 0 num; echo $num) \
'BEGIN{system("echo \"ibase=16;obase=2;"VAR"\"|bc");}'
解释:
-vVAR
将变量 VAR 传递给 Awk
-vVAR=$(read -p ... )
从
shell 给用户输入。
system("echo ... |bc")
使用 Awk 系统内置命令执行 shell 命令。请注意引用是如何在变量 VAR 处停止然后在它之后继续的,这样 Awk 将 VAR 解释为 Awk 变量而不是作为放入系统调用的字符串的一部分。
更新 - 在 Awk 变量中使用它:
awk -vVAR=$(read -p "Enter number: " -u 0 num; echo $num) \
'BEGIN{s="echo \"ibase=16;obase=2;"VAR"\"|bc"; s | getline awk_var;\
close(s); print awk_var}'
s | getline awk_var
会将命令 s
的输出放入 Awk 变量 awk_var
中。请注意,该字符串是在将其发送到 getline
之前构建的 - 如果不是(除非您将字符串连接括起来)Awk 将尝试将它发送到 getline
中的单独部分 %s VAR %s。
close(s)
关闭管道——尽管对于 bc
来说这无关紧要,Awk 在退出时自动关闭管道——如果你把它放到一个更复杂的 Awk 脚本中,最好明确地关闭管道。根据 Awk 文档,某些命令(例如 mail
将在完成之前等待管道关闭。
http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_39.html
根据您编写示例的方式,您似乎想要将 awk 记录( line )转换为关联数组。这是一个 awk 可执行脚本,它允许通过 运行 对 split
类型数组中的值执行 bc
命令:
#!/usr/bin/awk -f
{
# initialize the a array
cnt = split([=10=], a, FS)
if( convertArrayBase(10, 2, a, cnt) > -1 ) {
# use the array here
for(i=1; i<=cnt; i++) {
print a[i]
}
}
}
# Destructively updates input array, converting numbers from ibase to obase
#
# @ibase: ibase value for bc
# @obase: obase value for bc
# @a: a split() type associative array where keys are numeric
# @cnt: size of a ( number of fields )
#
# @return: -1 if there's a getline error, else cnt
#
function convertArrayBase(ibase, obase, a, cnt, i, b, cmd) {
cmd = sprintf("echo \"ibase=%d;obase=%d", ibase, obase)
for(i=1; i<=cnt; i++ ) {
cmd = cmd ";" a[i]
}
cmd = cmd "\" | bc"
i = 0 # reset i
while( (cmd | getline b) > 0 ) {
a[++i] = b
}
close( cmd )
return i==cnt ? cnt : -1
}
当与输入一起使用时:
1 2 3
4 s 1234567
此脚本输出以下内容:
1
10
11
100
0
100101101011010000111
convertArrayBase
函数对 split
类型数组进行操作。因此,在调用它之前,您必须使用整行(如图所示)或字段的子字段(未显示)初始化输入数组(此处为 a
)。它破坏性地更新数组。
您可以使用一些辅助文件直接调用 bc
以获得类似的输出。我没有发现 bc
支持 -
( stdin
作为文件名)所以
比我想要的多一点。
制作这样的 start_cmds
文件:
ibase=10;obase=2;
和 quit_cmd
喜欢:
;quit
给定一个输入文件(称为 data.semi
),其中数据由 ;
分隔,如下所示:
1;2;3
4;s;1234567
你可以运行bc
喜欢:
$ bc -q start_cmds data.semi quit_cmd
1
10
11
100
0
100101101011010000111
这与 awk 脚本输出的数据相同,但只调用 bc
一次所有输入。现在,虽然该数据不在脚本中的 awk 关联数组中,但 bc
输出可以作为 awk 的标准输入输入写入并重新组装到数组中,例如:
bc -q start_cmds data.semi quit_cmd | awk 'FNR==NR {a[FNR]=; next} END { for( k in a ) print k, a[k] }' -
1 1
2 10
3 11
4 100
5 0
6 100101101011010000111
最后一个破折号告诉 awk 将 stdin
视为输入文件,并允许您稍后添加其他文件进行处理。
我正在尝试在 awk 脚本中使用 bc。在下面的代码中,我试图将十六进制数转换为二进制数并将其存储在一个变量中。
#!/bin/awk -f
{
binary_vector = $(bc <<< "ibase=16;obase=2;FF")
}
我哪里出错了?
不是说这是个好主意但是:
$ awk 'BEGIN {
cmd = "bc <<< \"ibase=16;obase=2;FF\""
rslt = ((cmd | getline line) > 0 ? line : -1)
close(cmd)
print rslt
}'
11111111
另见 http://gnu.org/software/gawk/manual/gawk.html#Bitwise-Functions and http://gnu.org/software/gawk/manual/gawk.html#Nondecimal-Data
下面的一行 Awk 脚本应该做你想做的事:
awk -vVAR=$(read -p "Enter number: " -u 0 num; echo $num) \
'BEGIN{system("echo \"ibase=16;obase=2;"VAR"\"|bc");}'
解释:
-vVAR
将变量 VAR 传递给 Awk
-vVAR=$(read -p ... )
从
shell 给用户输入。
system("echo ... |bc")
使用 Awk 系统内置命令执行 shell 命令。请注意引用是如何在变量 VAR 处停止然后在它之后继续的,这样 Awk 将 VAR 解释为 Awk 变量而不是作为放入系统调用的字符串的一部分。
更新 - 在 Awk 变量中使用它:
awk -vVAR=$(read -p "Enter number: " -u 0 num; echo $num) \
'BEGIN{s="echo \"ibase=16;obase=2;"VAR"\"|bc"; s | getline awk_var;\
close(s); print awk_var}'
s | getline awk_var
会将命令 s
的输出放入 Awk 变量 awk_var
中。请注意,该字符串是在将其发送到 getline
之前构建的 - 如果不是(除非您将字符串连接括起来)Awk 将尝试将它发送到 getline
中的单独部分 %s VAR %s。
close(s)
关闭管道——尽管对于 bc
来说这无关紧要,Awk 在退出时自动关闭管道——如果你把它放到一个更复杂的 Awk 脚本中,最好明确地关闭管道。根据 Awk 文档,某些命令(例如 mail
将在完成之前等待管道关闭。
http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_39.html
根据您编写示例的方式,您似乎想要将 awk 记录( line )转换为关联数组。这是一个 awk 可执行脚本,它允许通过 运行 对 split
类型数组中的值执行 bc
命令:
#!/usr/bin/awk -f
{
# initialize the a array
cnt = split([=10=], a, FS)
if( convertArrayBase(10, 2, a, cnt) > -1 ) {
# use the array here
for(i=1; i<=cnt; i++) {
print a[i]
}
}
}
# Destructively updates input array, converting numbers from ibase to obase
#
# @ibase: ibase value for bc
# @obase: obase value for bc
# @a: a split() type associative array where keys are numeric
# @cnt: size of a ( number of fields )
#
# @return: -1 if there's a getline error, else cnt
#
function convertArrayBase(ibase, obase, a, cnt, i, b, cmd) {
cmd = sprintf("echo \"ibase=%d;obase=%d", ibase, obase)
for(i=1; i<=cnt; i++ ) {
cmd = cmd ";" a[i]
}
cmd = cmd "\" | bc"
i = 0 # reset i
while( (cmd | getline b) > 0 ) {
a[++i] = b
}
close( cmd )
return i==cnt ? cnt : -1
}
当与输入一起使用时:
1 2 3
4 s 1234567
此脚本输出以下内容:
1
10
11
100
0
100101101011010000111
convertArrayBase
函数对 split
类型数组进行操作。因此,在调用它之前,您必须使用整行(如图所示)或字段的子字段(未显示)初始化输入数组(此处为 a
)。它破坏性地更新数组。
您可以使用一些辅助文件直接调用 bc
以获得类似的输出。我没有发现 bc
支持 -
( stdin
作为文件名)所以
比我想要的多一点。
制作这样的 start_cmds
文件:
ibase=10;obase=2;
和 quit_cmd
喜欢:
;quit
给定一个输入文件(称为 data.semi
),其中数据由 ;
分隔,如下所示:
1;2;3
4;s;1234567
你可以运行bc
喜欢:
$ bc -q start_cmds data.semi quit_cmd
1
10
11
100
0
100101101011010000111
这与 awk 脚本输出的数据相同,但只调用 bc
一次所有输入。现在,虽然该数据不在脚本中的 awk 关联数组中,但 bc
输出可以作为 awk 的标准输入输入写入并重新组装到数组中,例如:
bc -q start_cmds data.semi quit_cmd | awk 'FNR==NR {a[FNR]=; next} END { for( k in a ) print k, a[k] }' -
1 1
2 10
3 11
4 100
5 0
6 100101101011010000111
最后一个破折号告诉 awk 将 stdin
视为输入文件,并允许您稍后添加其他文件进行处理。