J'ai un fichier journal qui doit être analysé et analysé. Le fichier contient quelque chose de similaire comme ci-dessous:
Fichier:
20141101 server contain dump
20141101 server contain nothing
{uekdmsam ikdas
jwdjamc ksadkek} ssfjddkc * kdlsdl
sddsfd jfkdfk
20141101 server contain dump
Sur la base du scénario ci-dessus, je dois vérifier si la ligne de départ ne contient pas de date ou de numéro que je dois ajouter à la ligne précédente.
Fichier de sortie:
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdl sddsfd jfkdfk
20141101 server contain dump
text-processing
sed
awk
William R
la source
la source
-0
si pour les enregistrements délimités NUL. Utilisez-0777
pour slurper le fichier entier en mémoire (ce dont vous n'avez pas besoin ici).Peut être un peu facile avec
sed
la première partie
:1;N;$!b1
rassemble toutes les lignes du fichier divisées par\n
1 longue lignela deuxième partie supprime le symbole de nouvelle ligne s'il suit le symbole non numérique avec des espaces possibles entre ses.
Pour éviter la limitation de mémoire (en particulier pour les gros fichiers), vous pouvez utiliser:
Ou oubliez un
sed
script difficile et rappelez-vous que l'année commence2
la source
tr '\n' $'\a' | sed $'s/\a\a*\( *[^0-9]\)/\1/g' | tr $'\a' '\n'
moi - même.+
est\{1,\}
.[\n]
n'est pas portable non plus.\n\{1,\}
serait POSIX.: 1;x
est de définir l'1;x
étiquette dans les seds POSIX. Donc , vous avez besoin:sed -e :1 -e 'N;$!b1' -e 's/\n\{1,\}\( *[^0-9]\)/\1/g'
. Notez également que de nombreusessed
implémentations ont une petite limite sur la taille de leur espace de motif (POSIX ne garantit que 10 x LINE_MAX IIRC).Une façon serait:
Cependant, cela supprime également la nouvelle ligne finale. Pour l'ajouter à nouveau, utilisez:
Explication
Le
-l
supprimera les sauts de ligne (et en ajoutera également un à chaqueprint
appel, c'est pourquoi j'utilise à laprintf
place. Ensuite, si la ligne actuelle commence par des nombres (/^\d+/
) et que le numéro de ligne actuel est supérieur à un ($.>1
, cela est nécessaire pour éviter d'ajouter un supplément ligne vide au début), ajoutez un\n
au début de la ligne pourprintf
imprimer chaque ligne.Alternativement, vous pouvez remplacer tous les
\n
caractères par\0
, puis changer à nouveau ceux\0
qui se trouvent juste avant une chaîne de chiffres\n
:Pour qu'il ne corresponde qu'à des chaînes de 8 chiffres, utilisez-le à la place:
la source
printf
est le format . Utilisationprintf "%s", $_
%10000000000s
par exemple.perl
,echo %.10000000000f | perl -ne printf
met ma machine à genoux.Essayez de faire cela en utilisant awk :
Pour l'utiliser:
la source
Un autre moyen plus simple (que mon autre réponse) en utilisant l' algorithme de awk et terdon :
la source
END{print ""}
. Alternative:awk -v ORS= 'NR>1 && /^[0-9]{8}/{print "\n"};1;END{print "\n"}'
la source
Le programme en bash:
sous une seule ligne:
Solution avec barres obliques inverses préservant (
read -r
) et espaces deIFS=
début (juste aprèswhile
):formulaire d'une ligne:
la source
n
. Il supprime également les espaces blancs. Mais vous pouvez utilisermksh
pour cela:while IFS= read -r L; do [[ $L = [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]* ]] && print; print -nr -- "$L"; done; print
Ça marchera
la source