Usando awk para um script bash que define um “conjunto mínimo de pacotes”
Eu gostaria de escrever um script com os seguintes requisitos:
- na entrada, obtenha uma lista de pacotes disponíveis via
apt. Lá você pode ter alguns pacotes que são instalados automaticamente por outros pacotes na lista. - na saída, fornece a mesma lista sem os pacotes que dependem de outros pacotes na lista.
Em outros termos, quero fazer em bash o que o usuário François G fez nesta resposta
Talvez algo assim já exista, mas às vezes eu gosto de escrever scripts para melhorar meu script bash e também para me divertir.
Na minha cabeça, já desenvolvi o script, mas estou com um problema técnico. Vamos supor que eu tenha a lista de dependências neste formato (é a maneira como se apt-rdependsexpressa):
useless-line-1
useless-line-2
useless-line-3
item-1
fixed-string substring-1-1
fixed-string substring-1-2
fixed-string substring-1-3
item-2
fixed-string substring-2-1
fixed-string substring-2-2
item-3
item-4
fixed-string substring-4-1
fixed-string substring-4-2
fixed-string substring-4-3
fixed-string substring-4-4
Quero extrair o parágrafo relacionado a item-1isto é:
fixed-string substring-1-1
fixed-string substring-1-2
fixed-string substring-1-3
Não sou um awkespecialista, mas acho que pode atender aos meus propósitos. Não consigo "construir" o comando correto. Devido ao fato de que item-2pode não ser conhecido, tentei:
# extract text between item-1 and the next line that starts without blank
$ awk '/item-1/,/^[A-Za-z0-9]/' deplist
item-1
mas item-1já se encaixa na condição ^[A-Za-z0-9], então não é bom. Além disso, quero excluir item-1e item-2da saída.
Qual é a melhor maneira de extrair essa parte dos dados?
Respostas
Você poderia fazer algo ex "com estado".
$ awk -v item='item-1' '$0 !~ /^[[:blank:]]/{p=0} $0 ~ "^" item {p=1} p' deplist
item-1
fixed-string substring-1-1
fixed-string substring-1-2
fixed-string substring-1-3
Como funciona:
definido
p=0sempre que combinamos uma linha que estrela com algo diferente de um espaço em branco horizontal (você pode usar seu original um pouco mais específico^[A-Za-z0-9]aqui)definir
p=1se correspondermos ao desejado^itemimprimir sempre
p==1
Essencialmente, "ligue a impressão quando combinarmos com o item desejado e desligue-a quando combinarmos qualquer outro item".
Você precisará de um pouco de lógica extra para pular a linha correspondida:
$ awk -v item='item-1' '
$0 !~ /^[[:blank:]]/{p=0} {m = $0 ~ "^" item ? 1 : 0} m {p=1} p && !m
' deplist
fixed-string substring-1-1
fixed-string substring-1-2
fixed-string substring-1-3
Aqui, executamos a mesma combinação, mas salvamos o resultado na variável m; em seguida, defina p=1quando mfor verdadeiro (esta parte é idêntica à que tínhamos antes); então, apenas imprimimos quando p==1e, m==0ou seja, pulamos a linha onde ocorre a correspondência real.