我有一个输入文件,每行有〜100行和〜100个字段。每个字段代表正值或负值。我希望打印$ 1,然后在每行中仅显示正或负字段。每行的正或负字段数是随机的。
0 x 9 8 7 -1 -2 -3
2 x 7 6 -2 -3 -4 -5
4 x 4 3 2 1 -6 -7
正面
0 9 8 7
2 7 6
4 4 3 2 1
阴性
0 -1 -2 -3
2 -2 -3 -4 -5
4 -6 -7
以上输出显示$ 1,然后在与$ 1相同的行中其余字段中显示正值或负值。
我尝试的当前代码(对于正值,请从输入的第6行开始):
awk 'NR>5{for(i=3; i<=NF; i++) if ( $i > 0 ) print $1, $i}' input > output
这工作正常,除了我打印如下输出:
0 9
0 8
0 7
2 7
2 6
4 4
4 3
4 2
4 1
我也尝试过:
awk 'BEGIN {ORS="\t"} NR>5 {print $1} {for(i=3;i<=NF;i++) if ( $i > 0 && i <= NF} {print $i}}' input > output
但是后来我再也不会在输出中移到新行了。如果我通过某种'else if(i = NF){ORS = ...}'条件将ORS改回\ n,那么它将在新行上打印每个i的所有字段输出,就像BEGIN语句无效一样。
我如何告诉awk打印$ 1,然后将来自同一输入行的所有其他输出打印到同一输出行,然后在输出中前进1新行并为下一条输入行重复该过程?
谢谢。
我尝试对两个文件循环执行此操作:
for j in 1 2; do
positive=ofile.p0
negative=ofile.m0
awk 'NR>5{
printf $1>"positive";
printf $1>"negative";
for(i=3;i<=NF;i++)
if($i~/[-+]?[0-9]+/)
if ($i>0) printf OFS $i>"positive";
else if($i<0) printf OFS $i>"negative";
print "">"positive";
print "">"negative";
}'ofile.0$j
mv positive $positive$j
mv negative $negative$j
done
但挂起。编辑:Tiw的答案已在printf中更新为%s。可以进行此更改。
答案 0 :(得分:2)
尝试一下:
awk 'NF>5{printf "%s",$1>"positive";printf "%s",$1>"negative"; for(i=2;i<=NF;i++) if($i~/^[-+]?[0-9]+$/) if ($i>0) printf "%s",OFS $i>"positive"; else if($i<0) printf "%s",OFS $i>"negative"; print "">"positive";print "">"negative";}' input
带有名为input
的文件:
0 x 9 8 7 -1 -2 -3
2 x 7 6 -2 -3 -4 -5
4 x 4 3 2 1 -6 -7
它将创建两个文件,
一个positive
:
0 9 8 7
2 7 6
4 4 3 2 1
一个negative
:
0 -1 -2 -3
2 -2 -3 -4 -5
4 -6 -7
多行输入以提高可读性:
awk 'NF>5{
printf "%s",$1>"positive";
printf "%s",$1>"negative";
for(i=2;i<=NF;i++)
if($i~/^[-+]?[0-9]+$/) ## Another and better way is $i == $i + 0
if ($i>0) printf "%s",OFS $i>"positive";
else if($i<0) printf "%s",OFS $i>"negative";
print "">"positive";
print "">"negative";
}' input
这很简单,所以我想您很容易理解。
请注意,在{}
和for
之后,我没有使用if
来引用块,因为它们之后都只有一个命令,因此可以保存引号。
print
将在末尾打印换行符\n
,而printf
则不会。
同样,NR
表示 R 个索引的 N 个,即行号,我改为NF
,表示 N F 的孩子,我想这就是您想要的。
if($i~/^[-+]?[0-9]+$/)
是要测试字段是否为数字。
如果该字段不会为空,则使用$i==$+0
是更好的方法。
结合测试该字段不是0
还是空字段,请使用$i && ($i==$i+0)
。
答案 1 :(得分:2)
您需要做的第一件事是检查字段是否为数字,如果是这种情况,则可以进行检查。在<?xml version="1.0" encoding="UTF-8"?>
<Response xmlns="http://tempuri.org/Response.xsd">
<ResponseStatusDescription />
<EntityPaymentReceiptNumber />
<Description>Test</Description>
<OperationName>CheckPayment</OperationName>
<BankID>39</BankID>
<EntityPaymentDate />
<CheckPaymentID>188721103486</CheckPaymentID>
<ResponseStatusCode>INFO2</ResponseStatusCode>
</Response>
中,可以通过将变量加零来检查变量是否为数字,并检查变量是否返回相同的值。
对于正数,您可以这样做:
awk
答案 2 :(得分:1)
如果选择Perl,
输入:
$ cat blaisem.txt
0 x 9 8 7 -1 -2 -3
2 x 7 6 -2 -3 -4 -5
4 x 4 3 2 1 -6 -7
$
+ ve和-ve分别运行
$ perl -ne ' @p=/(\S+)(?<=\d)/g;print "$p[0] "; for(@p[1..$#p]) { print "$_ " if $_ >=0 } print "\n" ' blaisem.txt
0 9 8 7
2 7 6
4 4 3 2 1
$ perl -ne ' @p=/(\S+)(?<=\d)/g;print "$p[0] "; for(@p[1..$#p]) { print "$_ " if $_ < 0 } print "\n" ' blaisem.txt
0 -1 -2 -3
2 -2 -3 -4 -5
4 -6 -7
$
+ ve和-ve在一个脚本中
$ perl -ne ' open(POS,">>pos.txt"); open(NEG,">>neg.txt"); @p=/(\S+)(?<=\d)/g;
print POS "$p[0] "; print NEG "$p[0] ";
for(@p[1..$#p]) { print NEG "$_ " if $_ < 0; print POS "$_ " if $_>=0 }
print POS "\n"; print NEG "\n" ' blaisem.txt
$ cat pos.txt
0 9 8 7
2 7 6
4 4 3 2 1
$ cat neg.txt
0 -1 -2 -3
2 -2 -3 -4 -5
4 -6 -7
$