Estou lendo um arquivo linha por linha. Cada linha fica assim:
xxyu: JHYU_IOPI
Cada linha é passada para o awk como abaixo. Quero imprimir a linha anterior do padrão correspondente; Eu posso conseguir isso com o grep e quero saber onde errei com o awk.
#!/bin/bash
while read i
do
awk '/$i/{print a}{a=$0}' ver_in.txt
done<in.txt
Eu também tentei isso:
#!/bin/bash
while read i
do
awk -v var="$i" '/var/{print a}{a=$0}' jil.txt
done<in.txt
Edit: usando awk depois de obter sugestão para não usar sh read. Minha entrada e saída desejada são mostradas abaixo:
EDIT 1: editou a entrada para o script @Ed Morton awk como abaixo
Arquivo de entrada: arquivo cat
/* ----------------- AIX_RUN_WATCH ----------------- */
insert_job: AIX_RUN_WATCH job_type: BOX
owner: root
permission:
date_conditions: 1
days_of_week: su
start_times: "22:00"
alarm_if_fail: 1
alarm_if_terminated: 1
group: app
send_notification: 0
notification_emailaddress:
/* ----------------- AIX_stop ----------------- */
insert_job: AIXstop job_type: CMD
box_name: AIX_RUN_WATCH
command: ls
machine: cfg.mc
owner: root
permission:
date_conditions: 0
box_terminator: 1
std_out_file: ">> /tmp/${AUTOSERV}.${AUTO_JOB_NAME}.$(date +%Y%m%d).stdout"
std_err_file: ">> /tmp/${AUTOSERV}.${AUTO_JOB_NAME}.$(date +%Y%m%d).stderr"
alarm_if_fail: 1
alarm_if_terminated: 1
group: app
send_notification: 1
/* ----------------- AIX_start ----------------- */
insert_job: AIX_start job_type: CMD
box_name: AIX_RUN_WATCH
command: ls
machine: cfg.mc
owner: root
permission:
date_conditions: 0
box_terminator: 1
std_out_file: ">> /tmp/${AUTOSERV}.${AUTO_JOB_NAME}.$(date +%Y%m%d).stdout"
std_err_file: ">> /tmp/${AUTOSERV}.${AUTO_JOB_NAME}.$(date +%Y%m%d).stderr"
alarm_if_fail: 1
alarm_if_terminated: 1
group: app
cat targets
box_name: AIX_RUN_WATCH
Saída esperada -
box_name: AIX_RUN_WATCH
insert_job: AIX_stop
insert_job: AIX_start
para a primeira tentativa, você precisa usar aspas duplas para a expansão da variável do shell e, em seguida, escapar do
$
operador awk para evitar que ele se expanda pelo shell, mas esteja ciente de que usar como este quebrará o awk caso a variável$i
contenha caracteres especiais como\
,/
. [Estou pulando para corrigir um ou mais problemas com seu comando agora].para a segunda tentativa, você precisa usar correspondência de regex ou correspondência de string na linha atual, como usar correspondência de regex (correspondência parcial de regex) com:
ou correspondência de string (correspondência de string completa) como:
agora, falando sobre os comandos que você está tentando usá-los para imprimir a linha anterior do padrão correspondente, você pode fazer tudo com o awk e parar usando o loop do shell; aqui estamos fazendo uma correspondência de string completa:
ou fazendo uma correspondência regex parcial:
ou fazendo correspondência de string parcial:
ou fazendo uma correspondência completa de regex:
Você não precisa de um loop de leitura while para isso, e fazer processamento de texto em sh é uma má ideia (consulte Por que usar um loop de shell para processar texto é considerado uma prática ruim? ).
Em vez disso, obtenha seu script awk para processar os dois arquivos.
Ao ler o primeiro arquivo (
in.txt
), ele cria uma expressão regular em uma variável chamada anexando cada linha de entrada e o operadorre
regex "alternância" (ou seja, OR ).Quando terminar de ler o primeiro arquivo, a primeira coisa que precisa é remover o final
|
do arquivore
. Isso é necessário porque semprere
acabará com caráter devido à forma como é construído. Se não o removermos, esse final fará com que o regex corresponda a todas as linhas de .|
|
ver_in.txt
Depois disso, imprima a variável
a
se a linha de entrada atual corresponder ao regex na variávelre
(isso imprimirá uma linha vazia se a primeira linha de ver_in.txt corresponderre
- porque a está vazia. Se você não quiser que isso aconteça, altere essa linha de$0 ~ re {print a}
para$0 ~ re && a != "" {print a}
).Então, se corresponde ou não, defina
a=$0
.NOTA: o
NR==FNR {... ; next}
é um idioma awk muito comum para manipular o primeiro arquivo de entrada de uma maneira diferente do segundo e dos arquivos de entrada subsequentes.NR
é o contador de linha global para todos os arquivos que estão sendo lidos, eFNR
é o contador de linha para o arquivo atual.... então seNR==FNR
, isso significa que estamos lendo o primeiro arquivo. Anext
instrução pula para a próxima linha de entrada, impedindo que o restante do script awk seja executado enquanto estiver no primeiro arquivo.Você não forneceu uma amostra de dados completa, então fiz o meu próprio para testar:
Este arquivo in.txt fará com que re seja igual
bar|foo|xxyu: JHYU_IOPI
BTW, porque o script awk está fazendo uma correspondência de regex com
re
, as linhasin.txt
são tratadas como expressões regulares, não como texto fixo. Isso significa que se você quiser que quaisquer caracteres especiais regex (como.
,|
,[
ou]
e muitos outros) em in.txt sejam tratados como caracteres literais, você precisará escapá-los com uma barra invertida .... você teria que fazer isso com seu loop sh+awk original também.Saída do script awk acima:
Não use um loop de shell para manipular texto, consulte Por que usar um loop de shell para processar texto é considerado uma prática ruim? . As pessoas que inventaram o shell também inventaram o awk para o shell chamar para manipular texto.
Usando qualquer awk em qualquer shell em cada caixa Unix:
Resposta original:
Consulte https://www.gnu.org/software/gawk/manual/gawk.html#Multiple-Line para saber como definir RS para null nos permite trabalhar com registros de várias linhas e, em seguida, definir FS para uma nova linha significa que cada campo em esse registro é uma linha inteira, portanto, estamos tratando seus dados como registros separados por linhas em branco, cada um contendo 2 linhas de dados.
Você mencionou ter algum outro arquivo de linhas ght que indica quais devem ser impressos, implicando que existem outros blocos que não devem ser impressos. Se você tiver um arquivo desse tipo e se parecer com isso:
e seu outro arquivo de entrada contém algumas
ght:
linhas que não correspondem ao acima, por exemplo, veja osght: whatever
blocos no arquivo de entrada modificado abaixo:então o código acima seria atualizado para: