将变量合并到bash代码行中

时间:2011-12-19 21:39:02

标签: bash variables awk

那么也许这不是最好的标题;但很难用简短的标题表达我的意图。

我在这里有一句话:

2   118610455   P2_PM_2_5034    T   <DUP:TANDEM>    40  .   END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP

基本上我想将其转换为:

2 118610455 118610566

所以主要的问题是从第8列开始这个118610566

我知道如何grep这个数字:

$c=`cat line|awk '{print $8}'|sed 's/;/\t/g'|awk '{print $1}'|sed 's/\END=//g'`

但我的问题是如何将此变量合并到另一个bash行中:

what_i_want=`cat line|awk '{print $1"\t"$2"\t"$c}'`

THX

3 个答案:

答案 0 :(得分:3)

可能会有所帮助 -

[jaypal:~/Temp] cat tmp
2   118610455   P2_PM_2_5034    T   <DUP:TANDEM>    40  .   END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP

[jaypal:~/Temp] var=$(awk -v FS="[ ;=]" '{print $1,$4,$24}' tmp)

[jaypal:~/Temp] echo $var
2 118610455 118610566

FSawk's内置变量。它默认为空格或制表符。由于您的行作为多个分隔符设置FS到一个字符类有助于拆分每个去限制器的行。我们在此定义的字符类是spacesemi-colonequal

可能会觉得有点奇怪,但我用这个作为我的调试工具来识别列,当我碰巧用一个以上的分隔符解析一行时。这就是我从你的行中得到的 -

[jaypal:~/Temp] awk -v FS="[ ;=]" '{for(i=1;i<=NF;i++) print "$"i" is "$i}' tmp
$1 is 2
$2 is 
$3 is 
$4 is 118610455
$5 is 
$6 is 
$7 is P2_PM_2_5034
$8 is 
$9 is 
$10 is 
$11 is T
$12 is 
$13 is 
$14 is <DUP:TANDEM>
$15 is 
$16 is 
$17 is 
$18 is 40
$19 is 
$20 is .
$21 is 
$22 is 
$23 is END
$24 is 118610566
$25 is SVLEN
$26 is 110
$27 is SVTYPE
$28 is TDUP
$29 is CIPOS
$30 is -100,55
$31 is CIEND
$32 is -56,100
$33 is IMPRECISE
$34 is DBVARID
$35 is esv7540
$36 is VALIDATED
$37 is VALMETHOD
$38 is CGH
$39 is SVMETHOD
$40 is RP

您还可以通过以下方式使用substr的简单awk内置函数 -

[jaypal:~/Temp] awk '{print $1,$2,$8=substr($8,5,9)}' tmp
2 118610455 118610566

答案 1 :(得分:1)

通过一些字符串操作,您可以一次性完成。

what_i_want=$(awk '{sub(/^END=/,"",$8); sub(/;.*$/,"",$8); print $1,$2,$8}' line)

一些解释:

sub(a,b,c)在变量a中搜索模式c并将其替换为b,将修改后的字符串存储回c。模式写在//

^是字符串的开头,$是结尾,.是任意内容,*表示前面的模式中的零个或多个。所以在我们的案例中:

sub(/^END=/,"",$8);在字符串的开头(END=)匹配^并将其替换为"",没有,基本上将其删除。

sub(/;.*$/,"",$8);.*中的所有内容(;)带到最后($)并删除它。请注意,在awk中,与大多数正则表达式引擎一样,* greedy ,这意味着它需要获得最长的匹配,因此我们知道这将获得第一个;

我们剩下的就是你想要的数字。

答案 2 :(得分:0)

如果您的“列”始终用空格分隔,那么您不需要使用子shell和awk,您可以直接在shell中执行此操作:

[ghoti@pc ~]$ read one two three four five junk <<< "2   118610455   P2_PM_2_5034    T   <DUP:TANDEM>    40  .   END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP"
[ghoti@pc ~]$ echo "$five"
<DUP:TANDEM>
[ghoti@pc ~]$ echo "$junk"
40 . END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP

read行中指定的最后一个变量获取“其他所有内容”。

另外。如果你正在处理这样的多行,你可以循环运行它:

cat /path/to/inputfile | while read one two three four five junk; do
  echo "$one - $two - $five"
done

盐味。