我试图抓取文本“time: X”后面的 100 行,其中 X 在 {0,40,80,...,200} 中。这是我到目前为止所拥有的:
#!/bin/bash
start=1
end=5
for i in $(seq $start $end);do
j=$(($i*40))
awk '/time: $j/{for(i=1;i<=100;i++}{getline;print}}' file > fileX-$j.txt
done
然而这似乎不起作用。我的问题具体是关于变量 $j 以及我需要如何在 '/time: ...' 之后定义它
例如,我有一个名为“file”的文件:
time: 1
1 2 3
1 33 1
2 31 4
time: 40
2 1 3
9 8 77
1 3 4
在这种情况下我想制作两个单独的文件;第一个包含
1 2 3
1 33 1
2 31 4
第二个是:
1 2 3
1 33 1
2 31 4
我尝试将 $j 作为变量传递,如 mazs 提到的,但仍然给我空文件。这是我的做法:
awk -v jj=$j '/time: jj/{for(i=1;i<3;i++){getline;print}}' file > fileX-$j.txt
答案1
有两个问题。第一个是 shell 不会$j
在单引号内展开:'$j'
告诉 shell 您需要字符串$j
,而不是变量的值j
。
在这种情况下,由于该值仅包含数字,因此您可以将其放在单引号之外:
awk '/time: '"$j"'/{for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
j
请注意,如果包含正则表达式特殊字符(.
、等)的值,*
那么这些字符将被解释为这样。例如
j='2*3'
awk '/foo '"$j"' bar/'
该脚本将打印包含诸如foo 3 bar
、foo 23 bar
、foo 223 bar
等内容而不是 的行foo 2*3 bar
。如果值中有 a,/
那么 awk 将看到正则表达式匹配结构的结尾;例如
j='2/3'
awk '/foo '"$j"' bar/'
会导致 awk 抱怨标记序列/foo 2/
, 3
, bar
,/
在语法上不正确。
您可以使用命令行选项为 awk 定义变量-v
:
j='a\tb'
awk -v j="$j" '{print j}'
请注意,这对 的值执行反斜杠扩展j
。例如,上面的代码片段将每一行替换为a↦b
制表↦
符。
但这并不直接适用于您的情况,因为 awk 不会扩展内部变量/…/
:/foo/
匹配字符串foo
,而不是变量的值foo
。要在正则表达式匹配中使用变量,您需要使用以下match
函数:
awk -v j="$j" 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
这适用于j
不包含反斜杠的值;斜杠就可以了。例如,如果j
设置为a/b*c
,这将匹配诸如 、 等之类的行time: a/c
。time: a/bc
如果j
设置为\t
,这将匹配包含time:
后跟空格和制表符的行。
要将 shell 变量的值传递给 awk,无论该值是什么,都要通过环境传递它。
export j
awk 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
或者,为了避免j
在脚本的其余部分停留在环境中:
j="$j" awk 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
如果您想搜索文字字符串而不是正则表达式,则可以使用该index
函数而不是match
.例如
j='a*b'
awk 'index($0, "time: "+j)'
打印包含time: a*b
.
答案2
您必须将 $j shell 变量传递给 awk:
awk -v jj="$j" '...'
请注意,这假设变量的值不包含反斜杠,因为参数 toawk -v
经历了反斜杠扩展。