I have some text files which contain some columns separated by a various number of spaces, but instead I need one single tab as a separator. Is it possible to do in Bash?
7 Answers
To convert sequences of more than one space to a tab, but leave individual spaces alone:
sed 's/ \+ /\t/g' inputfile > outputfile
To do this for a number of files:
for inputfile in *
do
sed 's/ \+ /\t/g' "$inputfile" > tmpfile && mv tmpfile "$inputfile"
done
or
for inputfile in *
do
sed -i.bak 's/ \+ /\t/g' "$inputfile"
done
or
find . -type f -exec sed -i.bak 's/ \+ /\t/g' {} \;
Use this form for MacOS (or simply to avoid escaping the +
in Linux):
sed -E 's/ + /\t/g'
along with other options, etc., that you need from the examples above.
-
-
@AaronFranke: What command did you try? None of the examples in my answer should produce that error. Feb 10, 2019 at 1:25
-
-
@AaronFranke: GNU
sed
doesn't like to have a space before the backup extension. I've edited my answer. Thanks for the report. Feb 10, 2019 at 13:22 -
this is not a good solution for some, because single column that just-so-happens to be separated by one space will not get converted to \t Apr 16, 2023 at 5:44
If your character is multiple tabs you can also use tr -s
:
-s, --squeeze-repeats replace each input sequence of a repeated character
that is listed in SET1 with a single occurrence
For example:
my_file.txt | tr -s " "
All white spaces will become one.
You can use sed
to replace a number of spaces with a tab.:
Example to replace one-or-more-spaces with one tab:
cat spaced-file | sed 's/ \+/\t/g' > tabbed-file
-
The OP said the number of spaces was variable, so I don't think this solution will work.– MikelFeb 2, 2011 at 22:35
-
@Mikel. Oops. Thanks for pointing that out. I've edit the post to allow matching for variable spaces. Feb 2, 2011 at 22:45
-
-
The easiest answer using only bash
is:
while read -r col1 col2 col3 ...; do
echo -e "$col1\t$col2\t$col3..."
done <file
If there are a variable number of columns, you can do this, but it will only work in bash
, not sh
:
while read -r -a cols; do
(
IFS=$'\t'
echo "${cols[*]}"
)
done <file
e.g.
while read -r -a cols; do
(
IFS=$'\t'
echo "${cols[*]}"
)
done <<EOF
a b c
d e f
g h i
EOF
produces:
a b c
d e f
g h i
(there is a tab in between each, but it's hard to see when I paste it here)
You could also do it using sed
or tr
, but notice that the handling of blanks at the start produces different results.
sed:
$ sed 's/ */\t/g' << EOF
a b c
d e f
g h i
EOF
a b c
d e f
g h i
tr:
$ tr -s ' ' '\t' <<EOF
a b c
d e f
g h i
EOF
a b c
d e f
g h i
Try the following SED script:
sed 's/ */<TAB>/g' <spaces-file > tabs-file
Where <TAB> is pressing the TAB key.
This is a very simple solution:
sed -E 's/\s+/\t/g' your_file > new_file
sed basically works in this manner (sed 's/old_pattern/new_pattern/g').
In this case the old pattern is "\s+" which means find space "s" one or more time "+" and the back slash "\" to interpret that as regular expression.
The new pattern is tab "\t" which is written in regular expression format and the "g" is apply the replacement to all lines "globally".
-
1Hello and welcome to superuser. You should take the time to explain your solution. For someone not familiar with *nix systems, sed and regular expressions, this looks like a pile of weird characters.– MoggetApr 3, 2016 at 21:43