我有一个数字,以逗号分隔的列表:
123711184642,02,3583090366663629,639f02012437d4
123715942138,01,3538710295145500,639f02afd6c643
123711616258,02,3548370476972758,639f0200485732
我需要在第3列分成三个如下:
123711184642,02,3583090366663629,639f02,0124,37d4
123715942138,01,3538710295145500,639f02,afd6,c643
123711616258,02,3548370476972758,639f02,0048,5732
和转换数字在最后两个栏为十进制:
123711184642,02,3583090366663629,639f02,292,14292
123715942138,01,3538710295145500,639f02,45014,50755
123711616258,02,3548370476972758,639f02,72,22322
下面是对乔纳森的回答变化:
awk $([[ $(awk --version) = GNU* ]] && echo --non-decimal-data) -F, '
BEGIN {OFS = FS}
{
$6 = sprintf("%d", "0x" substr($4, 11, 4))
$5 = sprintf("%d", "0x" substr($4, 7, 4))
$4 = substr($4, 1, 6)
print
}'
我包括它是否需要添加--non-decimal-data选项的相当扭曲的方式。
编辑
只是它的挫折感,这里的纯猛砸相当于:
saveIFS=$IFS
IFS=,
while read -r -a line
do
printf '%s,%s,%d,%d\n' "${line[*]:0:3}" "${line[3]:0:6}" "0x${line[3]:6:4}" "0x${line[3]:10:4}"
done
IFS=$saveIFS
所述"${line[*]:0:3}"
(引述*
)的工作方式类似于AWK的OFS
在于它会导致击的IFS
(此处为逗号)上输出阵列元件之间插入。我们可以通过插入数组元素如下一种更接近于平行我上面的AWK版本需要该功能的另一个优点。
saveIFS=$IFS
IFS=,
while read -r -a line
do
line[6]=$(printf '%d' "0x${line[3]:10:4}")
line[5]=$(printf '%d' "0x${line[3]:6:4}")
line[4]=$(printf '%s' "${line[3]:0:6}")
printf '%s\n' "${line[*]}"
done
IFS=$saveIFS
不幸的是,猛砸不允许printf -v
(这类似于sprintf()
)进行分配数组元素,所以printf -v "line[6]" ...
不起作用。
编辑:作为猛砸4.1,printf -v
现在可以进行分配给数组元素。例:
printf -v 'line[6]' '%d' "0x${line[3]:10:4}"
需要围绕阵列参考引号,以防止可能的文件名匹配。如果一个名为“LINE6”文件在当前目录中存在与参考是没有报价,那么一个变量命名line6
将包含printf的输出来创建(或更新)。闲来无事有关文件,如它的内容,将开始发挥作用。只有名字 - 只有切线。
这似乎工作:
awk -F, '{ p1 = substr($4, 1, 6);
p2 = ("0x" substr($4, 7, 4)) + 0;
p3 = ("0x" substr($4, 11, 4)) + 0;
printf "%s,%s,%s,%s,%d,%d\n", $1, $2, $3, p1, p2, p3;
}'
为您的样品输入数据,它产生:
123711184642,02,3583090366663629,639f02,292,14292
123715942138,01,3538710295145500,639f02,45014,50755
123711616258,02,3548370476972758,639f02,72,22322
随后加入0力加“0x”加4位十六进制的字符串连接awk
对待数字为十六进制数。
您可以简化这个来:
awk -F, '{ p1 = substr($4, 1, 6);
p2 = "0x" substr($4, 7, 4);
p3 = "0x" substr($4, 11, 4);
printf "%s,%s,%s,%s,%d,%d\n", $1, $2, $3, p1, p2, p3;
}'
以0x前缀字符串被迫向printf()
和%d
格式时为整数。
上面的代码与在MacOS X 10.6.5(版本20070501)天然awk
精美的作品;可悲的是,它不与GNU gawk
3.1.7工作。也就是说,现在看来,是根据POSIX允许的行为(见下面的评论)。然而,gawk
具有非标准功能strtonum
可用于将它棍棒成执行正确 - 可惜钝击是必要的。
gawk -F, '{ p1 = substr($4, 1, 6);
p2 = "0x" substr($4, 7, 4);
p3 = "0x" substr($4, 11, 4);
printf "%s,%s,%s,%s,%d,%d\n", $1, $2, $3, p1, strtonum(p2), strtonum(p3);
}'
这个答案集中展示了如何通过AWK可移植做转换。
使用--non-decimal-data
为GAWK根据GNU Awk User's Guide不推荐。并使用strtonum()
是不可移植。
在下列实施例的每个记录的第一个字被转换。
做转换的最简便的方式是通过用户定义的函数AWK [reference]:
function parsehex(V,OUT)
{
if(V ~ /^0x/) V=substr(V,3);
for(N=1; N<=length(V); N++)
OUT=(OUT*16) + H[substr(V, N, 1)]
return(OUT)
}
BEGIN { for(N=0; N<16; N++)
{ H[sprintf("%x",N)]=N; H[sprintf("%X",N)]=N } }
{ print parsehex($1) }
您可以使用此
awk '{cmd="printf %d 0x" $1; cmd | getline decimal; close(cmd); print decimal}'
但速度相对较慢。下面一个是速度更快,如果你有很多换行分隔的十六进制数转换:
awk 'BEGIN{cmd="printf \"%d\n\""}{cmd=cmd " 0x" $1}END{while ((cmd | getline dec) > 0) { print dec }; close(cmd)}'
如果很多参数都增加了对单一printf命令有可能是一个问题。
在我的经验,按照Linux的作品:
awk -Wposix '{printf("%d\n","0x" $1)}'
我在Ubuntu Linux操作系统进行测试14.04它由GAWK,mawk和原始的awk。通过原始awk的命令显示一条警告消息,但您可以通过在shell重定向指令2>/dev/null
隐藏它。如果你不想这样做,你可以剥除-Wposix
在原始的awk这样的情况:
awk $(awk -Wversion >/dev/null 2>&1 && printf -- "-Wposix") '{printf("%d\n","0x" $1)}'
(在bash 4,你可以通过更换>/dev/null 2>&1
&>/dev/null
)
注:-Wposix招可能不与在OS X中使用NAWK和一些BSD操作系统变种工作,虽然。
cat all_info_List.csv| awk 'BEGIN {FS="|"}{print $21}'| awk 'BEGIN {FS=":"}{p1=$1":"$2":"$3":"$4":"$5":"; p2 = strtonum("0x"$6); printf("%s%02X\n",p1,p2+1) }'
上述命令打印“all_info_List.csv”,一个文件,其中字段分隔符是内容的“|”。然后采取字段21(MAC地址),并且使用字段分隔符分割为“:”。将其分配给变量 “p1
” 前5个字节每个MAC地址的,因此,如果我们有该MAC地址: “11:22:33:44:55:66”,p1
将是:“11:22:33:44 :55:”。 p2
被分配的最后一个字节的十进制值:“0x66”将会分配“102”十进制到p2
。最后,我使用printf
加入p1
和p2
,而转换p2
回十六进制,增加一个到它后。
这可能会为你(GNU SED和printf的)工作:
sed -r 's/(....)(....)$/ 0x\1 0x\2/;s/.*/printf "%s,%d,%d" &/e' file
拆分最后八个字符,并添加由十六进制标识符之前的领域空间,然后评估用printf整条生产线。
printf "%d\n", strtonum( "0x"$1 )"
Perl版本,用帽子@Jonathan的提示:
perl -F, -lane '$p1 = substr($F[3], 0, 6); $p2 = substr($F[3], 6, 4); $p3 = substr($F[3], 10, 4); printf "%s,%s,%s,%s,%d,%d\n", @F[0..2], $p1, hex($p2), hex($p3)' file
-a
打开自动分割模式,来填充@F
阵列
-F,
改变自动分割隔板,
(默认为空格)
的substr()
指数比它们AWK当量少1,因为Perl阵列从0开始。
输出:
123711184642,02,3583090366663629,639f02,292,14292
123715942138,01,3538710295145500,639f02,45014,50755
123711616258,02,3548370476972758,639f02,72,22322