57

I know how to select a field from a line using the cut command. For instance, given the following data:

a,b,c,d,e
f,g,h,i,j
k,l,m,n,o

This command:

cut -d, -f2 # returns the second field of the input line

Returns:

b
g
l

My question: How can I select the second field counting from the end? In the previous example, the result would be:

d
i
n
ssn
  • 673
  • 1
  • 5
  • 6

3 Answers3

83

Reverse the input before and after cut with rev:

<infile rev | cut -d, -f2 | rev

Output:

d
i
n
Thor
  • 16,942
  • 3
  • 52
  • 69
19

Try doing this with :

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

Or using :

perl -F, -lane 'print $F[-2]' file.txt

Or using (thanks manatwork) :

ruby -F, -lane 'print $F[-2]' file.txt

Or using bash (thanks manatwork) :

while IFS=, read -ra d; do echo "${d[-2]}"; done < file.txt

Or using :

cat file.txt |
python -c $'import sys\nfor line in sys.stdin:\tprint(line.split(",")[-2])'
Gilles Quénot
  • 31,569
  • 7
  • 64
  • 82
  • 1
    `bash` not needs fixed column count for this: `while IFS=, read -ra d; do echo "${d[-2]}"; done < file.txt`. – manatwork Feb 13 '13 at 15:03
  • 1
    BTW, your third solution also works if you change `perl` with `ruby`. – manatwork Feb 13 '13 at 15:08
  • Thanks, `ruby` added, `bash` edited. – Gilles Quénot Feb 13 '13 at 15:39
  • 1
    If the 4th field may start with `-` or (depending on the environment, shell, or how the shell was compiled), may contain backslash characters, then `echo` is not an option. Why do you need to con`cat`enate `file.txt` with _nothing_ before feeding it to `python`!?. You need `read -A` instead of `read -a` in `ksh93` and `zsh`. Negative subscripts work in `zsh` but only in recent versions of `ksh93` and `bash`. In older versions, you can use `${d: -2:1}` – Stéphane Chazelas Feb 13 '13 at 16:01
  • 2
    @StephaneChazelas, I think you mean `${d[@]: -2:1}` in your last sentence. – manatwork Feb 15 '13 at 08:17
  • @manatwork, yes sorry, thanks for the correction. – Stéphane Chazelas Feb 15 '13 at 10:58
  • I suspected this answer came from someone called Gilles, only it happens to be different from the Gilles I suspected. The same Gilles under a different name perhaps? – vfclists Dec 28 '19 at 19:01
0

Using sed:

sed -E 's/^([^,]*,)*([^,]*)(,[^,]*){1}$/\2/' infile

Output:

d
i
n

Explanation

  • ([^,]*,)* matches any number of non-comma charecter followed by a comma, i.e. any number of columns.
  • ([^,]*) matches a column.
  • (,[^,]*){1} matches one column at the end, if you change the quantifier {1} to {2} it matches the third column from the end etc.
Thor
  • 16,942
  • 3
  • 52
  • 69