I think you're looking for expand
and/or unexpand
. It seems you're trying to ensure a \t
ab width counts as 8 chars rather than the single one. fold
will do that as well, but it will wrap its input to the next line rather than truncating it. I think you want:
expand < input | cut -c -80
expand
and unexpand
are both POSIX specified:
- The
expand
utility shall write files or the standard input to the standard output with \t
ab characters replaced with one or more space characters needed to pad to the next tab stop. Any backspace characters shall be copied to the output and cause the column position count for tab stop calculations to be decremented; the column position count shall not be decremented below zero.
Pretty simple. So, here's a look at what this does:
unset c i; set --;
until [ "$((i+=1))" -gt 10 ]; do set -- "$@" "$i" "$i"; done
for c in 'tr \\t \ ' expand; do eval '
{ printf "%*s\t" "$@"; echo; } |
tee /dev/fd/2 |'"$c"'| {
tee /dev/fd/3 | wc -c >&2; } 3>&1 |
tee /dev/fd/2 | cut -c -80'
done
The until
loop at top gets a set of data like...
1 1 2 2 3 3 ...
It printf
s this with the %*s
arg padding flag so for each of those in the set printf
will pad with as many spaces as are in the number of the argument. To each one it appends a \t
ab character.
All of the tee
s are used to show the effects of each filter as it is applied.
And the effects are these:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
66
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8
105
Those rows are lined up in two sets like...
- output of
printf ...; echo
- output of
tr ...
or expand
- output of
cut
- output of
wc
The top four rows are the results of the tr
filter - in which each \t
ab is converted to a single space.
And the bottom four the results of the expand
chain.
Based on your description, suppose that we have, as input, a tab-separated file like:
$ cat file
1 2 3 4 c.2458C>T 6
a b c d c.45_46delAA or f
a1 b2 c3 d4 p.Ala78_Arg80del f6
Using sed
To find the first integer from the fifth column:
$ sed -r 's/([^\t]*\t){4}[^[:digit:]]*([[:digit:]]+).*/\2/' file
2458
45
78
The above was tested on GNU sed
. For OSX or other BSD system, try:
sed -E 's/([^\t]*\t){4}[^[:digit:]]*([[:digit:]][[:digit:]]*).*/\2/' file
Using awk
$ awk '{sub(/^[^[:digit:]]*/, "", $5); sub(/[^[:digit:]].*/, "", $5); print $5;}' file
2458
45
78
Best Answer
You can change the tab stops in your terminal using the terminal database, which you can access several ways from C++ (for example, ncurses). You can also access it from shell using
tput
.You'd want to start by clearing the tabs (
tput tbc
). Then move the cursor to each column you want a tab stop in (tput hpa 10
for column 10, for example). Then finally set the tab stop (tput hts
). Repeat the positioning and tab setting for each tab stop you want. Example: