2017-01-29 1 views
0

Je me demandais quelle serait la meilleure façon de tout obtenir après la deuxième occurrence d'une chaîne. J'ai des fichiers comme ceci:Comment retourner tout après la 2ème occurrence de chaîne

--- 
title: Test Document 
creation_date: 01-29-2016 
--- 

Text, blah blah blah 
More text, blah blah blah 

J'ai donc le fichier qui contient « frontmatter » entre deux --- s. Je voudrais retourner tout après la seconde ---, de préférence en utilisant une commande bash de quelque sorte. En pensant à cela, sed et awk sont venus à l'esprit, mais je ne sais pas vraiment lequel serait le mieux pour le travail.

Une partie importante de ceci est qu'il peut y avoir n'importe quelle quantité arbitraire de paire clé-valeur dans le frontmatter, donc juste couper les quatre premières lignes n'est pas une approche valide ici.

+0

Il est préférable d'expliquer avec une entrée exacte que vous avez une sortie exacte que vous voulez. – Inian

+0

Si vous envisagez vraiment de faire beaucoup de requêtes automatisées, un format de fichier différent est en ordre. Cela semble être conçu pour un balayage rapide par un œil humain, et non une analyse programmatique. – chepner

+3

En essayant de savoir si vous devriez utiliser sed ou awk pour tout problème: sed est pour des substitutions simples sur des lignes individuelles (** c'est tout **), awk est pour tout le reste. Le problème que vous décrivez n'est pas une simple substitution sur une ligne individuelle et par conséquent ce n'est pas un travail pour sed, c'est un travail pour awk. Si vous essayez d'utiliser sed pour autre chose, vous vous retrouverez rapidement dans un enfer de runes indéchiffrables, de problèmes de portabilité, d'inefficacité et à peu près tous les autres attributs indésirables du logiciel. –

Répondre

2

Avec sed vous pouvez supprimer une plage de lignes entre deux motifs:

sed '/---/,/---/d' file 

D'autres lignes sont affichées automatiquement.

More about sed features.

Si vous souhaitez supprimer les lignes ci-dessus aussi, vous pouvez utiliser celui-ci:

sed '1{:a;N;/---.*---/d;ba}' file 

détails:

1 # if the current line is the first one 
{ 
    :a # define a label "a" 
    N # append the next line to the pattern space 
    /---.*---/d # delete the pattern space when the pattern succeeds 
    ba # go to label "a" 
} 

Notez que la commande d arrête le scénario sans condition et sed continue avec les lignes restantes.

+1

Cela imprimera les lignes au-dessus du premier '---'; pas clair si c'est un problème pour l'OP ... – dawg

+0

@dawg: J'ai ajouté une autre version pour le faire. –

+0

sed -rn '1 {: X/---/{H; g;/--- \ n ---/d}; n; bX}; p 'fichier – mug896

3

En utilisant awk vous pouvez le faire:

awk 'p>1; /---/{++p}' file 

Text, blah blah blah 
More text, blah blah blah 
1

Voici une solution pure Bash:

while IFS= read -r line || [[ -n $line ]]; do 
    if [[ "$line" =~ ^--- ]]; then 
     ((++count)) 
    elif [ $count -ge 2 ]; then 
     echo "$line" 
    fi 
done <file 

Vous pouvez utiliser awk dans une sed comme manière à imprimer tout en dehors de cette plage de correspondance de motif comme si:

awk '/^---/,/^---/ {next} 1' file