chaimp
chaimp

Reputation: 17877

How to split a string in bash delimited by tab

I'm trying to split a tab delimitted field in bash.

I am aware of this answer: how to split a string in shell and get the last field

But that does not answer for a tab character.

I want to do get the part of a string before the tab character, so I'm doing this:

x=`head -1 my-file.txt`
echo ${x%\t*}

But the \t is matching on the letter 't' and not on a tab. What is the best way to do this?

Thanks

Upvotes: 47

Views: 121166

Answers (7)

Kevin Buchs
Kevin Buchs

Reputation: 2872

The answer from https://stackoverflow.com/users/1815797/gniourf-gniourf hints at the use of built in field parsing in bash, but does not really complete the answer. The use of the IFS shell parameter to set the input field separate will complete the picture and give the ability to parse files which are tab-delimited, of a fixed number of fields, in pure bash.

echo -e "a\tb\tc\nd\te\tf" > myfile
while IFS='<literaltab>' read f1 f2 f3;do echo "$f1 = $f2 + $f3"; done < myfile

a = b + c
d = e + f

Where, of course, is replaced by a real tab, not \t. Often, Control-V Tab does this in a terminal.

Upvotes: 1

Denis Capart
Denis Capart

Reputation: 41

There is an easy way for a tab separated string : convert it to an array.

Create a string with tabs ($ added before for '\t' interpretation) :

AAA=$'ABC\tDEF\tGHI'

Split the string as an array using parenthesis :

BBB=($AAA) 

Get access to any element :

echo ${BBB[0]}
ABC
echo ${BBB[1]}
DEF
echo ${BBB[2]}
GHI

Upvotes: 4

user9118869
user9118869

Reputation: 109

read field1 field2 <<< ${tabDelimitedField}

or

read field1 field2 <<< $(command_producing_tab_delimited_output)

Upvotes: 10

Luchostein
Luchostein

Reputation: 2444

x=first$'\t'second
echo "${x%$'\t'*}"

See QUOTING in man bash

Upvotes: 3

glenn jackman
glenn jackman

Reputation: 247022

Use $'ANSI-C' strings in the parameter expansion:

$ x=$'abc\tdef\tghi'
$ echo "$s"
abc     def     ghi
$ echo ">>${x%%$'\t'*}<<"
>>abc<<

Upvotes: 21

Fredrik Pihl
Fredrik Pihl

Reputation: 45670

If your file look something like this (with tab as separator):

1st-field   2nd-field

you can use cut to extract the first field (operates on tab by default):

$ cut -f1 input
1st-field

If you're using awk, there is no need to use tail to get the last line, changing the input to:

1:1st-field     2nd-field
2:1st-field     2nd-field
3:1st-field     2nd-field
4:1st-field     2nd-field
5:1st-field     2nd-field
6:1st-field     2nd-field
7:1st-field     2nd-field
8:1st-field     2nd-field
9:1st-field     2nd-field
10:1st-field    2nd-field

Solution using awk:

$ awk 'END {print $1}' input
10:1st-field

Pure bash-solution:

#!/bin/bash

while read a b;do last=$a; done < input
echo $last

outputs:

$ ./tab.sh 
10:1st-field

Lastly, a solution using sed

$ sed '$s/\(^[^\t]*\).*$/\1/' input
10:1st-field

here, $ is the range operator; i.e. operate on the last line only.

For your original question, use a literal tab, i.e.

x="1st-field    2nd-field"
echo ${x%   *}

outputs:

1st-field

Upvotes: 76

Michael
Michael

Reputation: 4100

Use awk.

echo $yourfield | awk '{print $1}'

or, in your case, for the first field from the the last line of a file

tail yourfile | awk '{x=$1}END{print x}'

Upvotes: 10

Related Questions