我正在尝试在awk脚本中使用bc。在下面的代码中,我试图将十六进制数转换为二进制并将其存储在变量中。
#!/bin/awk -f
{
binary_vector = $(bc <<< "ibase=16;obase=2;FF")
}
我哪里出错了?
答案 0 :(得分:2)
不是说这是一个好主意,但是:
$ 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和http://gnu.org/software/gawk/manual/gawk.html#Nondecimal-Data
答案 1 :(得分:1)
以下单线程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 ... )
设置变量VAR
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
答案 2 :(得分:0)
顺便说一下你编写的例子,看起来你想将awk记录(行)转换为关联数组。这是一个awk可执行脚本,允许通过对bc
类型数组中的值运行split
命令来实现:
#!/usr/bin/awk -f
{
# initialize the a array
cnt = split($0, 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
输出可以写为awdin的stdin输入并重新组合成一个数组,如:
bc -q start_cmds data.semi quit_cmd | awk 'FNR==NR {a[FNR]=$1; next} END { for( k in a ) print k, a[k] }' -
1 1
2 10
3 11
4 100
5 0
6 100101101011010000111
最后一个破折号告诉awk将stdin
视为输入文件,并允许您稍后添加其他文件进行处理。