如果给出下面的字符串,如何使用awk或sed获得第14和第15位来替换第6和第7位。
xxxxx02xxxxxx89xx
xxxxx22xxxxxx33xx
输出
xxxxx89xxxxxx89xx
xxxxx33xxxxxx33xx
我是新手,对不起我的问题。
答案 0 :(得分:3)
sed命令很简单,但很难阅读:
sed 's/\(.....\)..\(......\)\(..\)/\1\3\2\3/'
可以使用Gnu awk
(但不是其他awk变种)可能更易维护的解决方案。但是,请参见下文。):
gawk -v FIELDWIDTHS="5 2 6 2 999" -v OFS='' '{$2=$4;print}'
FIELDWIDTHS
变量定义了5个固定宽度字段:前5个字符,后两个字符(位置6和7);接下来的六个字符(8到13);接下来的两个字符(14和15);和下一个(最多)999个字符,应该是该行的其余部分。 (如果你有更长的线,必要时增加)。将OFS
设置为空对于固定长度字段通常很有用;它阻止awk
在输出中的字段之间插入空格。
FIELDWIDTHS
是GNU awk扩展。但是,在Posix awk
中重新实现很容易。这是一个简单的实现:
function fieldwidth_set( i) {
if (PROCINFO["FS"]) FIELDWIDTHS = FIELDWIDTHS;
else if (length(FIELDWIDTHS)) {
_FW_NF = split(FIELDWIDTHS, _FW_ARRAY);
for (i in _FW_ARRAY) {
if (_FW_ARRAY[i] !~ /^[0-9]+$/) {
printf "Illegal value '%s' in FIELDWIDTHS\n", _FW_ARRAY[i] >>"/dev/stderr";
exit 1;
}
_FW_ARRAY[i]+=0;
}
} else
_FW_NF = 0;
}
function set_fieldwidth(fw) { FIELDWIDTHS=fw; fieldwidth_set(); }
function fw_( a,i,k) {
if (_FW_NF) {
a = $0;
$0 = "";
k=1;
for (i=1; i<=_FW_NF; ++i) {
$i = substr(a, k, _FW_ARRAY[i]);
k+=_FW_ARRAY[i];
}
}
}
BEGIN{set_fieldwidth()}
{fw_()}
据我所知,只有Gnu awk允许您在awk
命令行上混合程序文件和程序文本。 Posix需要-f program-file
选项,可以重复,但不需要Gnu awk实现的-e program-text
选项。因此,如果您想将上述代码段与命令行awk程序一起使用,则需要执行以下操作:
awk -v FIELDWIDTHS="5 2 6 2 999" -v OFS= -f fw.awk -f <(echo '{$2=$4;print}')
(假设您将fieldwidth代码段放入fw.awk
。)
为提高效率,fw.awk
坚持要求您通过致电FIELDWIDTHS
告诉您已更改fieldwidth_set()
。或者,您可以使用set_fieldwidth("....")
将FIELDWIDTHS
设置为新值。它将与GNU awk以及其他awk实现一起使用;它让GNU awk做了繁重的工作。
答案 1 :(得分:2)
你可以试试下面的sed命令,
$ echo 'xxxxx03xxxxxx75xx' | sed -r 's/^(.{5})(..)(.{6})../\1\2\3\2/g'
xxxxx03xxxxxx03xx
$ echo 'xxxxx03xxxxxx75xx' | sed 's/^\(.\{5\}\)\(..\)\(.\{6\}\)../\1\2\3\2/g'
xxxxx03xxxxxx03xx
它用位置6和7中的数字替换第14和第15位数字。
$ echo 'xxxxx03xxxxxx75xx' | sed -r 's/^(.{5})..(.{6})(..)/\1\3\2\3/g'
xxxxx75xxxxxx75xx
$ echo 'xxxxx03xxxxxx75xx' | sed 's/^\(.\{5\}\)..\(.\{6\}\)\(..\)/\1\3\2\3/g'
xxxxx75xxxxxx75xx
它用第14和第15位的数字替换第6和第7位数字。
答案 2 :(得分:2)
这应该遵循您的请求并与所有awk
合作:
awk '{$6=$14;$7=$15}1' FS= OFS= file
xxxxx89xxxxxx89xx
xxxxx33xxxxxx33xx
它会将位置6
中的数字更改为14
中的数字,将7
中的数字更改为15
如果FS=""
不起作用,请尝试以下操作:
awk '{n=split($0,a,"");a[6]=a[14];a[7]=a[15];for (i=1;i<=n;i++) printf "%s",a[i];print ""}' input
在其中一条评论中提出要求:
It works, thanks! How about if I want to replace 14th and 15th digit by 6th and 7th digit? – Vision111
awk '{$14=$6;$15=$7}1' FS= OFS= file
答案 3 :(得分:1)
这将在没有GNU awk GAWK
awk 'sub(/[0-9]+/,substr($0,14,2))' file
或更长但更通用的
awk '{print substr($0,0,5) substr($0,14,2) substr($0,8)}' file
结果:
xxxxx89xxxxxx89xx
xxxxx33xxxxxx33xx