web-dev-qa-db-fra.com

Comment obtenir l'avant-dernier champ d'une commande de coupe

J'ai un ensemble de données en entrée et j'ai besoin de l'avant-dernier champ basé sur le délimiteur. Les lignes peuvent avoir différents nombres de délimiteurs. Comment obtenir l'avant-dernier champ?

exemple d'entrée

text,blah,blaah,foo
this,is,another,text,line

production attendue

blaah
text
43
Archit Jain

Vous avez un indice de coupe Unix sauf les deux derniers jetons et capable de comprendre la réponse:

cat datafile | rev | cut -d '/' -f 2 | rev
80
Archit Jain

Awk convient bien à cela:

awk -F, '{print $(NF-1)}' file

La variable NF est une variable awk spéciale qui contient le nombre de champs dans l'enregistrement en cours.

40
Chris Seymour

Il n'est pas nécessaire d'utiliser cut, rev ou tout autre outil externe à bash ici. Il suffit de lire chaque ligne dans un tableau et de choisir la pièce que vous souhaitez:

while IFS=, read -r -a entries; do
  printf '%s\n' "${entries[${#entries[@]} - 2]}"
done <file

Faire cela en pure bash est beaucoup plus rapide que de démarrer un pipeline, au moins pour des entrées raisonnablement petites. Pour les grandes entrées, le meilleur outil est awk.

6
Charles Duffy

Solution Perl similaire à la solution awk de @iiSeymour

Perl -lane 'print $F[-2]' file

Ces options de ligne de commande sont utilisées:

  • n boucle autour de chaque ligne du fichier d'entrée, n'imprime pas automatiquement chaque ligne

  • l supprime les sauts de ligne avant le traitement et les réintègre ensuite

  • a mode autosplit - divise les lignes d'entrée dans le tableau @F. Par défaut, la division sur un espace blanc

  • e exécute le code Perl

Le @F le tableau autosplit commence à l'index [0] tandis que les champs awk commencent par $ 1
-1 est le dernier élément
-2 est l'avant-dernier élément

3
Chris Koknat

Code pour GNU sed :

 $ echo text, blah, blaah, foo | sed -r 's/^ (\ S +,) {2} (\ S +),. */\ 2 /'
 blaah 
 
 $ echo this, is, another, text, line | sed -r 's/^ (\ S +,) {2} (\ S +),. */\ 2 /'
texte

Exemple de code similaire à awkcode de Sudo_O:

 $ sed -r 's /.*, (\ w +),\w + $/\ 1 /' fichier 
 blaah 
 texte 

Il pourrait être préférable d'utiliser des programmes plus spécialisés pour les fichiers CSV, par exemple. awk ou Excel .

2
captcha

La réponse la plus minimaliste à ce problème est d'utiliser mon utilitaire cuts:

$ cat file.txt
text,blah,blaah,foo
this,is,another,text,line

$ cuts -2 file.txt
blaah
text

coupes , qui signifie "coupe sur les stéroïdes":

- automatically figures out the input field separators
- supports multi-char (and regexp) separators
- automatically pastes (side-by-side) multiple columns from multiple files
- supports negative offsets (from end of line)
- has good defaults to save typing + allows the user to override them

et beaucoup plus.

J'ai écrit cuts après avoir été frustré par les trop nombreuses limitations de cut sur Unix. Il est conçu pour remplacer divers combos cut/paste, le découpage et le découpage en colonnes de plusieurs fichiers, avec de multiples variantes de séparateur, tout en imposant une frappe minimale de la part de l'utilisateur.

Vous pouvez obtenir cuts (logiciel gratuit, licence artistique) sur github: https://github.com/arielf/cuts/

L'appel de cuts sans arguments affichera un message détaillé de Usage.

2
arielf