sed ou awk: supprime n lignes suivant un motif


106

Comment mélanger des modèles et des plages numériques dans sed (ou tout autre outil similaire - awk par exemple)? Ce que je veux faire, c'est faire correspondre certaines lignes dans un fichier et supprimer les n lignes suivantes avant de continuer, et je veux faire cela dans le cadre d'un pipeline.

Réponses:


189

Je vais essayer ça.

Pour supprimer 5 lignes après un motif (y compris la ligne avec le motif):

sed -e '/pattern/,+5d' file.txt

Pour supprimer 5 lignes après un motif (à l'exclusion de la ligne avec le motif):

sed -e '/pattern/{n;N;N;N;N;d}' file.txt

14
Notez que le +Nmodèle est une extension GNU. Remplacez le premier npar un Ndans votre deuxième exemple pour qu'il inclue la ligne avec le motif.
Suspendu jusqu'à nouvel ordre.

2
comment supprimer toutes les lignes après la correspondance du motif? J'utilise sed -e '/ <! - # content end -> </div> /, $ d' out.txt mais cela donne une erreur en disant: sed: -e expression # 1, char 24: caractères supplémentaires après commande Merci d'avance.
N mol

8
Ce qui se passe est similaire mais légèrement différent dans chaque cas. Dans la première recette, /pattern/,+5définit une plage, qui commence par une ligne contenant "pattern" ( /pattern/) et se termine 5 lignes plus tard ( +5). Le dernier caractère dest une commande à exécuter sur chaque ligne de cette plage, qui est «supprimer». Dans la deuxième recette, au lieu de faire correspondre une plage, il correspond juste à la ligne contenant le motif ( /pattern/), puis exécute une série de commandes {n;N;N;N;N;d}:, qui imprime essentiellement la ligne suivante ( n), puis lit et finalement supprime les 4 lignes suivantes ( N;N;N;N;d).
pimlottc

18
Sur les systèmes Mac / OS X, vous devez ajouter un point-virgule avant le crochet fermant:sed -e '/pattern/{n;N;N;N;N;d;}' file.txt
AvL

1
Par souci d'exhaustivité: Pour supprimer toutes les lignes suivant un certain modèle, something faites :,sed -E '/^something$/,$d'-Eest l'expression régulière étendue de portabilité POSIX.
not2qubit

7

Sans extensions GNU (par exemple sur macOS):

Pour supprimer 5 lignes après un motif (y compris la ligne avec le motif)

 sed -e '/pattern/{N;N;N;N;d;}'

Ajouter -i ''pour modifier sur place.


6

Des awksolutions simples :

Supposons que l'expression régulière à utiliser pour rechercher les lignes correspondantes est stockée dans la variable shell $regexet le nombre de lignes à ignorer $count.

Si la ligne correspondante doit également être ignorée (les $count + 1lignes sont ignorées):

... | awk -v regex="$regex" -v count="$count" \
  '$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'

Si la ligne correspondante ne doit pas être ignorée (les $countlignes après le match sont sautées):

... | awk -v regex="$regex" -v count="$count" \
  '$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1'

Explication:

  • -v regex="$regex" -v count="$count"définit des awkvariables basées sur des variables shell du même nom.
  • $0 ~ regex correspond à la ligne d'intérêt
    • { skip=count; next }initialise le compte de sauts et passe à la ligne suivante, sautant effectivement la ligne correspondante; dans la 2ème solution, l' printavant nextgarantit qu'il n'est pas ignoré.
    • --skip >= 0 décrémente le nombre de sauts et prend des mesures s'il est (toujours)> = 0, ce qui implique que la ligne à portée de main doit être ignorée.
    • { next } passe à la ligne suivante, sautant effectivement la ligne actuelle
  • 1est un raccourci couramment utilisé pour { print }; c'est-à-dire que la ligne courante est simplement imprimée
    • Seules les lignes non concordantes et non sautées atteignent cette commande.
    • La raison qui 1équivaut à { print }est qu'il 1est interprété comme un modèle booléen qui, par définition, évalue toujours vrai, ce qui signifie que son action associée (bloc) est exécutée sans condition. Puisqu'il n'y a pas d' action associée dans ce cas, par awkdéfaut , l' impression de la ligne.

3

Cela pourrait fonctionner pour vous:

cat <<! >pattern_number.txt
> 5 3
> 10 1
> 15 5
> !
sed 's|\(\S*\) \(\S*\)|/\1/,+\2{//!d}|' pattern_number.txt |
sed -f - <(seq 21)
1 
2
3
4
5
9
10
12
13
14
15
21

10
Wow, c'est cryptique.
pimlottc

3
Une solution intelligente (bien que spécifique à GNU-Sed), mais peu de gens en bénéficieront, sauf si vous ajoutez une explication. pattern_number.txtest un fichier à 2 colonnes contenant le motif à faire correspondre dans la 1ère colonne, et dans la 2ème le nombre de lignes à sauter. La première sedcommande transforme le fichier en un sedscript qui effectue la correspondance et le saut correspondants; ce script est fourni via -fet stdin ( -) à la 2ème sedcommande. La 2ème sedcommande opère sur un exemple de fichier d'entrée ad-hoc formé à partir de la sortie de seq 21pour démontrer que cela fonctionne.
mklement0

En outre, la solution comporte une mise en garde: la méthode qu'elle utilise pour ne pas sauter la première ligne (celle correspondant au modèle) a pour effet secondaire de ne pas sauter les lignes en double dans la plage.
mklement0

C'est une utilisation impressionnante de sed.
Travis Rodman

3

Utiliser Perl

$ cat delete_5lines.txt
1
2
3
4
5 hello
6
7
8
9
10
11 hai
$ perl -ne ' BEGIN{$y=1} $y=$.  if /hello/ ; print if $y==1 or $.-$y > 5 ' delete_5lines.txt
1
2
3
4
11 hai
$

2

Cette solution vous permet de passer "n" comme paramètre et elle lira vos motifs à partir d'un fichier:

awk -v n=5 '
    NR == FNR {pattern[$0]; next}
    {
        for (patt in pattern) {
            if ($0 ~ patt) {
                print # remove if you want to exclude a matched line
                for (i=0; i<n; i++) getline
                next
            }
        }
        print
    }
' file.with.patterns -

Le fichier nommé "-" signifie stdin pour awk, il convient donc à votre pipeline


2
awk est capable de ressembler beaucoup plus à Perl que je ne le pensais!
Martin DeMello
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.