8

I have a number -> 12345

I want output in below format

1+2+3+4+5

echo `cat fl.txt | paste -s -d ''`

gives only 12345.

But when I add this + at the below command it gives same 12345.

echo `cat fl.txt | paste -s -d '' | tr -s '' '+'`
3

7 Answers 7

10

With GNU sed, you can also do:

sed 's/./+&/2g'
6

It's easier to split a string into characters:

fold -w1 file | paste -sd+ -

Some versions of the fold command do not have the -c option but have the -w option. In this case, they will be interchangeable.
or:

grep -o '.' file | paste -sd+ -

Perhaps with one command:

awk -v OFS='+' -F '' '{$1=$1; print}' file

And:

sed 's/\B/+/g' file
0
3

With zsh:

$ number=12345
$ printf '%s\n' ${(j[+])${(s[])number}}
1+2+3+4+5

s[] parameter expansion flag to split $number into its character components. j[+] to join them back with +.

With bash:

$ number=12345
$ shopt -s extglob
$ tmp=${number//@()/+}
$ printf '%s\n' "${tmp#+}"
1+2+3+4+5

${number//@()/+} replaces all the occurrences of nothing with +. For some reason ${number///+} doesn't seem to work in bash (it works in zsh though).

2

If you're loooking for shell-only, this is bash:

input=1245
output=""
while IFS= read -r -n1 char; do output+="${char}+"; done < <(printf %s "$input")
output=${output%+}
echo "$output"         # => 1+2+4+5

The odd looking < <(printf %s "$input") is a process substitution that redirects the input, with no trailing newline, into the while-read loop.

Or sed

output=$( sed 's/./&+/g; s/+$//' <<<"$input")
1
  • 1
    Probably not an issue with the OP's input (meant to be a number), but note that the read approach assumes $input contains no character of $IFS nor newlines. Oct 25, 2020 at 15:33
2

just some other possibilities using perl instead of awk or sed:

echo 12345 | perl -lpe '$_ = join "+", split //;'

or (if the number is saved in fl.txt)

# echo 12345 > fl.txt
perl -lpe '$_ = join "+", split //;' fl.txt

the -l param just avoids the line ending being included (when joining with "+"). otherwise you'd have 1+2+3+4+5+ as result.

alternatively you can use the method, similar as the one mentioned for sed already:

perl -pe 's/.\K/+/g; s/\+$//;' fl.txt

or

perl -pe 's/.\K(?!$)/+/g;' fl.txt

or

perl -pe 's/\B/+/g;' fl.txt

output in all cases:

1+2+3+4+5
0

Split/Join Characters with Ruby

There are lots of ways to do this. On way is to use Ruby to split your string into characters, and then join them back together with the + symbol. For example, at the shell prompt:

$ ruby -e 'puts ARGV.first.chars.join "+"' 12345
1+2+3+4+5
0

Using Raku (formerly known as Perl_6)

~$ echo 12345 | raku -ne 'put .comb.join("+");'
1+2+3+4+5

#OR

~$ echo 12345 | raku -pe '.=comb; .=join("+");'
1+2+3+4+5

Raku is a programming language in the Perl-family of programming languages. The code above uses Raku's new comb routine, which sifts through the input text to break around (and select out) a desired sequence, converse to the action of the split operator. Without any parameters, comb() breaks before/after each character. Here, because the target sequence is digits, comb(/ \d /) might prove useful:

% echo abcd12345efgh | raku -ne 'put .comb(/ \d /).join("+");'
1+2+3+4+5

#OR

% echo abcd12345efgh | raku -pe '.=comb(/ \d /); .=join("+");'
1+2+3+4+5

This isn't to say that other options aren't available. Below are solutions in a similar vein to the excellent Perl solutions posted by @uvularer_frikativ:

~$ echo 12345 | raku -pe '$_ = join "+", .split: "", :skip-empty;'
1+2+3+4+5

#OR

~$ echo 12345 > 12345.txt
~$ raku -pe '$_ = join "+", .split: "", :skip-empty;'  12345.txt
1+2+3+4+5

Some more Raku options:

~$ raku -pe 's:g/ )> . /+/;  s/^\+//;' 12345.txt
1+2+3+4+5

#OR

~$ raku -pe 's:g/<!after ^> )> . /+/;' 12345.txt
1+2+3+4+5

#OR

~$ raku -pe 's:g/ <?after . >  <!before $ > /+/;' 12345.txt
1+2+3+4+5

#OR

~$ raku -pe 's:g/<ww>/+/;' 12345.txt
1+2+3+4+5

http://raku.org

You must log in to answer this question.

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