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
1

3 Answers 3

83

Reverse the input before and after cut with rev:

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

Output:

d
i
n
2
  • 2
    I have many small snippets in my bin folder. rcut is for precisely this: #!/bin/bash rev | cut "$@" | rev Jan 16, 2017 at 15:07
  • 6
    It's too bad cut can't take negative field indices (like Python). Apr 9, 2018 at 4:55
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])'
7
  • 1
    bash not needs fixed column count for this: while IFS=, read -ra d; do echo "${d[-2]}"; done < file.txt.
    – manatwork
    Feb 13, 2013 at 15:03
  • 1
    BTW, your third solution also works if you change perl with ruby.
    – manatwork
    Feb 13, 2013 at 15:08
  • Thanks, ruby added, bash edited. Feb 13, 2013 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 concatenate 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} Feb 13, 2013 at 16:01
  • 2
    @StephaneChazelas, I think you mean ${d[@]: -2:1} in your last sentence.
    – manatwork
    Feb 15, 2013 at 8:17
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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .