Você tem que passar a variável shell $ j para awk:
awk -v jj="$j" '...'
Observe que isso pressupõe que o valor da variável não contenha barras invertidas, pois o argumento para awk -v
é submetido à expansão de barra invertida.
Eu estou tentando pegar 100 linhas após o texto "time: X" com X em {0,40,80, ..., 200}. Aqui está o que eu tenho até agora:
#!/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
No entanto, isso não parece funcionar. Minha pergunta especificamente é sobre a variável $ j e como eu preciso defini-la logo após '/ time: ...'
Por exemplo, eu tenho um arquivo chamado 'file':
time: 1
1 2 3
1 33 1
2 31 4
time: 40
2 1 3
9 8 77
1 3 4
Eu gostaria de criar dois arquivos separados nesse caso; primeiro contendo
1 2 3
1 33 1
2 31 4
e o segundo com:
1 2 3
1 33 1
2 31 4
Eu tentei passar $ j como uma variável como mazs mencionou, mas ainda me dá arquivos vazios. Aqui está como eu fiz:
awk -v jj=$j '/time: jj/{for(i=1;i<3;i++){getline;print}}' file > fileX-$j.txt
Você tem que passar a variável shell $ j para awk:
awk -v jj="$j" '...'
Observe que isso pressupõe que o valor da variável não contenha barras invertidas, pois o argumento para awk -v
é submetido à expansão de barra invertida.
Existem dois problemas. A primeira é que o shell não expande $j
dentro de aspas simples: '$j'
informa ao shell que você deseja a string $j
, não o valor da variável j
.
Nesse caso, como o valor contém apenas dígitos, você pode colocá-lo fora das aspas simples:
awk '/time: '"$j"'/{for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
Observe que, se o valor de j
continha caracteres especiais regexp ( .
, *
, etc.), esses caracteres seriam interpretados como tal. Por exemplo
j='2*3'
awk '/foo '"$j"' bar/'
o script imprime linhas contendo itens como foo 3 bar
, foo 23 bar
, foo 223 bar
, etc. e não foo 2*3 bar
. E se houvesse um /
no valor, o awk veria o final da construção de correspondência de expressão regular; por exemplo
j='2/3'
awk '/foo '"$j"' bar/'
resultaria em awk reclamando que a sequência de tokens /foo 2/
, 3
, bar
, /
não está sintaticamente correta.
Você pode definir uma variável para um awk com a opção de linha de comando -v
:
j='a\tb'
awk -v j="$j" '{print j}'
Observe que isso realiza uma expansão de barra invertida no valor de j
. Por exemplo, o snippet acima substitui cada linha por a↦b
, em que ↦
é um caractere de tabulação.
Mas isso não funciona diretamente no seu caso, porque o awk não expande variáveis dentro de /…/
: /foo/
corresponde à string foo
, não o valor da variável foo
. Para usar uma variável em uma correspondência de expressão regular, você precisaria usar a função match
:
awk -v j="$j" 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
Este funciona para valores de j
que não contêm uma barra invertida; uma barra está ok. Por exemplo, com j
definido como a/b*c
, isso corresponderia a linhas como time: a/c
, time: a/bc
, etc. Com j
definido como \t
, isso corresponderia às linhas contendo time:
seguido por um espaço e uma aba.
Para passar o valor de uma variável do shell para o awk, não importa qual seja o valor, passe-o pelo ambiente.
export j
awk 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
ou, para evitar que j
permaneça no ambiente pelo resto do script:
j="$j" awk 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
E se você quisesse pesquisar uma string literal, em vez de uma expressão regular, poderia usar a função index
em vez de match
. Por exemplo
j='a*b'
awk 'index($0, "time: "+j)'
imprime linhas contendo time: a*b
.