Comment utiliser une commande shell pour nafficher que la première colonne et la dernière colonne dun fichier texte?

Jai besoin daide pour comprendre comment utiliser la commande sed pour nafficher que la première colonne et la dernière colonne dun fichier texte. Voici ce que jai jusquà présent pour la colonne 1:

cat logfile | sed "s/\|/ /"|awk "{print $1}" 

Ma faible tentative pour afficher également la dernière colonne a été:

cat logfile | sed "s/\|/ /"|awk "{print $1}{print $8}" 

Cependant, cela prend la première colonne et la dernière colonne et les fusionne dans une liste. Existe-t-il un moyen dimprimer clairement la première colonne et les dernières colonnes avec les commandes sed et awk?

Exemple dentrée:

foo|dog|cat|mouse|lion|ox|tiger|bar 

Commentaires

  • Veuillez fournir un exemple d’entrée.

Réponse

Presque là. Mettez simplement les deux références de colonne lune à côté de lautre.

cat logfile | sed "s/|/ /" | awk "{print $1, $8}" 

Notez également que vous navez pas besoin de cat ici .

sed "s/|/ /" logfile | awk "{print $1, $8}" 

Notez également que vous pouvez indiquer à awk que les séparateurs de colonnes sont |, au lieu de blancs, vous navez donc pas besoin de sed non plus.

awk -F "|" "{print $1, $8}" logfile 

Selon les suggestions de Caleb , si vous voulez une solution qui affiche toujours le dernier champ , même sil ny en a pas exactement huit, vous pouvez utiliser $NF.

awk -F "|" "{print $1, $NF}" logfile 

Aussi, si vous voulez le sortie pour conserver les séparateurs |, au lieu dutiliser un espace, vous pouvez spécifier les séparateurs de champ de sortie. Malheureusement, cest un peu plus maladroit que dutiliser simplement lindicateur -F, mais voici trois approches.

  • Vous pouvez affecter lentrée et les séparateurs de champ de sortie dans awk lui-même, dans le bloc BEGIN.

    awk "BEGIN {FS = OFS = "|"} {print $1, $8}" logfile 
  • Vous pouvez affecter ces variables lors de lappel de awk depuis la ligne de commande, via lindicateur -v.

    awk -v "FS=|" -v "OFS=|" "{print $1, $8}" logfile 
  • ou simplement:

    awk -F "|" "{print $1 "|" $8}" logfile 

Commentaires

  • Bon travail pour expliquer comment ce problème peut être simplifié. Vous pouvez ajouter une note expliquant comment utiliser | comme séparateur de sortie au lieu de lespace par défaut pour la concaténation de chaînes. Vous pouvez également expliquer lutilisation de $NF au lieu du codage en dur $8 pour obtenir la dernière colonne.
  • ensuite comment mettre à jour le fichier?
  • @pankajprasad Écrire dans un nouveau fichier avec h > puis écrasez lancien ou utilisez sponge. Cest vraiment une nouvelle question.
  • @Sparhawk ça marche, mais le contenu de lalésage est effacé. comment gérer cela?
  • @pankajprasad Vous devez poser une nouvelle question. Cliquez sur le gros bouton bleu en haut qui dit  » Poser la question « .

Réponse

Vous utilisez quand même awk:

awk "{ print $1, $NF }" file 

Commentaires

  • wouldn ‘ t vous devez spécifier le séparateur de champ de saisie (car dans ce cas il semble être | plutôt que lespace) avec -F\| ou similaire? Et sil voulait utiliser le même délimiteur pour la sortie?
  • @Caleb Probablement: jattendais que lOP confirme à quoi exactement lentrée ressemblait, plutôt que dessayer de estimation basée sur les exemples qui ne fonctionnent pas …
  • Notez que cela suppose que lentrée contient au moins 2 champs.
  • @St é phaneChazelas OP a clairement indiqué dans le code quil a toujours huit champs.
  • @ michaelb958 Je pense  » clairement  » surestime le cas, juste un peu 🙂

Réponse

Remplacez simplement du premier au dernier | avec un | (ou un espace si vous préférez):

sed "s/|.*|/|/" 

Notez que même sil ny a « pas dimplémentation sed| est spécial (tant que étendu régulier les expressions ne sont pas activées via -E ou dans certaines implémentations), \| lui-même est spécial dans certains comme GNU sed. Vous ne devez donc pas échapper à | si vous voulez qu’il corresponde au caractère |.

Si vous remplacez par un espace et si lentrée peut déjà contenir des lignes avec un seul |, alors, vous « devrez traiter cela spécialement comme |.*| ne correspondra pas à ceux-ci.Cela pourrait être:

sed "s/|\(.*|\)\{0,1\}/ /" 

(cest-à-dire rendre la partie .*| facultative) Ou:

sed "s/|.*|/ /;s/|/ /" 

ou:

sed "s/\([^|]*\).*|/\1 /" 

Si vous voulez les premier et huitième champs quel que soit le nombre de champs dans lentrée, alors cest juste:

cut -d"|" -f1,8 

(tout cela fonctionnerait avec nimporte quel utilitaire compatible POSIX en supposant lentrée forme du texte valide (en particulier, les sed ne fonctionneront généralement pas si lentrée contient des octets ou des séquences doctets qui ne forment pas de caractères valides dans la locale actuelle comme par exemple printf "unix|St\351phane|Chazelas\n" | sed "s/|.*|/|/" dans un environnement local UTF-8)).

Réponse

Si vous vous trouvez sans problèmes et sans sed, vous pouvez atteindre le même chose avec coreutils:

paste <( cut -d"|" -f1 file) \ <(rev file | cut -d"|" -f1 | rev) 

Commentaires

  • cut est plus propre et plus compact que awk / sed lorsque vous êtes simplement intéressé par la première colonne, ou si les délimiteurs sont fixes (cest-à-dire pas un nombre variable despaces).
  • Assez élégant!

Réponse

Il semble que vous essayiez dobtenir le premier et le dernier champs de texte délimités par |.

Jai supposé que votre fichier journal contenait le texte comme ci-dessous,

foo|dog|cat|mouse|lion|ox|tiger|bar bar|dog|cat|mouse|lion|ox|tiger|foo 

Et vous voulez la sortie comme,

foo bar bar foo 

Si oui, alors voici la commande pour vos « s

Via GNU sed,

sed -r "s~^([^|]*).*\|(.*)$~\1 \2~" file 

Exemple:

$ echo "foo|dog|cat|mouse|lion|ox|tiger|bar" | sed -r "s~^([^|]*).*\|(.*)$~\1 \2~" foo bar 

Commentaires

  • Les colonnes ne sont pas délimitées par un tube | mais ils sont en colonnes, je suis intéressé à utiliser sed mais pas à utiliser la commande awk comme vous lavez fait dans votre commande: sed -r ‘ s ~ ^ ([^ |] *) . * \ | (. *) $ ~ \ 1 \ 2 ~ ‘ file
  •  » Les colonnes sont non délimité par un tuyau | mais ils sont dans les colonnes « , vous voulez dire que les colonnes sont séparées par des espaces?
  • Un exemple dentrée et une sortie seraient mieux.

Réponse

Vous devriez probablement le faire avec sed – je le ferais de toute façon – mais, juste car personne na encore écrit celui-ci:

while IFS=\| read col1 cols do printf %10s%-s\\n "$col1 |" " ${cols##*|}" done <<\INPUT foo|dog|cat|mouse|lion|ox|tiger|bar INPUT 

OUTPUT

 foo | bar 

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *