鉴于下面的string,如何使用awk或sed获取第14位和第15位来replace第6位和第7位。
xxxxx02xxxxxx89xx xxxxx22xxxxxx33xx
产量
xxxxx89xxxxxx89xx xxxxx33xxxxxx33xx
我在这里是新手,对我的问题感到抱歉。
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
坚持告诉你已经通过调用fieldwidth_set()
改变了FIELDWIDTHS
。 或者,您可以使用set_fieldwidth("....")
将FIELDWIDTHS
设置为新值。 它将与GNU awk以及其他awk实现一起工作; 它可以让GNU awk完成繁重的工作。
你可以尝试下面的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位数字。
这应该遵循您的要求,并与所有awk
工作:
awk '{$6=$14;$7=$15}1' FS= OFS= file xxxxx89xxxxxx89xx xxxxx33xxxxxx33xx
它会改变位置6
的数字14
和1中的一个与整数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
这将无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