Effectuer des opérations sed sur des numéros de ligne donnés

8

Je me demande s'il existe un moyen simple de fonctionner sur certaines lignes avec des numéros de ligne préassignés.

Disons que je veux sortir les 1ère, 7ème, 14ème et 16ème lignes d'un fichier, je peux simplement faire

sed -n '1p;7p;14p;16p' input_file

mais cela devient plus compliqué lorsque l'opération ne consiste pas seulement à imprimer, et je ne veux pas écrire la même commande longue 4 fois (et oui, je sais que je peux construire cette longue commande sed en substituant la même variable bash 4 fois, mais ce n'est pas assez idéal ...), c'est à dire

sed -n '1{long_command};7{long_command};14{long_command};16{long_command}' input_file

Existe-t-il un moyen d'effectuer l'opération sur ces lignes spécifiques de mon fichier? J'attends quelque chose comme

sed -n '1,7,14,16p'

qui ne fonctionnera certainement pas sous la forme actuelle.

Toute aide serait appréciée. "Non ce n'est pas possible." avec explications est aussi une réponse que j'accepterai.

Weijun Zhou
la source
c'est facile avecawk
RomanPerekhrest

Réponses:

11

Vous pouvez utiliser des branches:

sed '
  1b1
  7b1
  14b1
  16b1

  # for the rest to be left alone, branch off (or delete them with "d"):
  b

  :1
  long_command'

(notez que vous pouvez également ajouter des 20,25b1plages /re/b1de lignes ou inclure des lignes correspondant à re).

Ou vous pouvez utiliser awk:

awk 'NR == 1 || NR == 7 || ... {stuff}'

Ou en utilisant un hachage:

awk -v l=1,7,14,16 '
  BEGIN{split(l, a, ","); for (i in a) lines[a[i]]}

  NR in lines {stuff}'

(ou BEGIN{lines[1]lines[7]lines[14]lines[16]}s'il n'y en a pas trop)

Stéphane Chazelas
la source
Merci, je n'ai jamais pensé aux branches ... Il semble que ce soit l'outil idéal à utiliser dans ce cas.
Weijun Zhou
comment utiliser des branches comme celle-ci dans sed avec un modèle de recherche? comme dire que je veux faire correspondre ou supprimer un motif après la nième ligne?
qodeninja
3

Inversez simplement votre sélection et supprimez-la:

sed '2,6d;8,13d;15d;17,$d;long_command'
Philippos
la source
C'est aussi une bonne solution, bien qu'un peu plus difficile à gérer, par exemple, les numéros de ligne lus depuis stdin.
Weijun Zhou
1

Première variante:

Vous pouvez utiliser cette astuce:

sed -nf <(printf '%dp\n' 1 7 14 16)

-f fichier-script - ajoute le contenu du fichier script aux commandes à exécuter.

Essai

seq 1 20 | sed -nf <(printf '%dp\n' 1 7 14 16)

Production

1
7
14
16

Deuxième variante:

Au début, l'auxiliaire sedest utilisé pour filtrer uniquement les lignes nécessaires du fichier, puis ces lignes sont redirigées vers le principal sedavec la commande longue.

sed -n '1p; 7p; 14p; 16p' input.txt | sed 'long command'
MiniMax
la source