Can sed
make something like :
12345
become :
1&2&3&4&5
?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityWith GNU sed
:
sed 's/./\&&/2g'
(s
ubstitute every (g
) character (.
) with the same (&
) preceded with &
(\&
) but only starting from the second occurrence (2
)).
Portably:
sed 's/./\&&/g;s/&//'
(replace every occurrence, but then remove the first &
which we don't want).
With some awk
implementations (not POSIX as the behaviour is unspecified for an empty FS):
awk -F '' -v OFS="&" '{$1=$1;print}'
(with gawk
and a few other awk
implementations, an empty field separator splits the records into its character constituents. The output field separator (OFS
) is set to &
. We assign a value to $1
(itself) to force the record to be regenerated with the new field separator before printing it, NF=NF
also works and is slightly more efficient in many awk implementations but the behaviour when you do that is currently unspecified by POSIX).
perl
:
perl -F -lape '$_=join"&",@F'
(-pe
runs the code for every line, and prints the result ($_
); -l
strips and re-adds line endings automatically; -a
populates @F
with input split on the delimiter set in -F
, which here is an empty string. The result is to split every character into @F
, then join them up with '&', and print the line.)
Alternatively:
perl -pe 's/(?<=.)./&$&/g'
(replace every character provided it's preceded by another character (look-behind regexp operator (?<=...))
Using zsh
shell operators:
in=12345
out=${(j:&:)${(s::)in}}
(again, split on an empty field separator using the s::
parameter expansion flag, and join with &
)
Or:
out=${in///&} out=${out#?}
(replace every occurrence of nothing (so before every character) with &
using the ${var//pattern/replacement}
ksh operator (though in ksh
an empty pattern means something else, and yet something else, I'm not sure what in bash
), and remove the first one with the POSIX ${var#pattern}
stripping operator).
Using ksh93
shell operators:
in=12345
out=${in//~(P:.(?=.))/\0&}
(~(P:perl-like-RE)
being a ksh93 glob operator to use perl-like regular expressions (different from perl's or PCRE's though), (?=.)
being the look-ahead operator: replace a character provided it's followed by another character with itself (\0
) and &
)
Or:
out=${in//?/&\0}; out=${out#?}
(replace every character (?
) with &
and itself (\0
), and we remove the superflous one)
Using bash
shell operators:
shopt -s extglob
in=12345
out=${in//@()/&}; out=${out#?}
(same as zsh
's, except that you need @()
there (a ksh glob operator for which you need extglob
in bash
)).
Unix utilities:
fold -w1|paste -sd\& -
Explained:
"fold -w1"
- will wrap an each input character to its own line
fold - wrap each input line to fit in specified width
-w, --width=WIDTH use WIDTH columns instead of 80
%echo 12345|fold -w1
1
2
3
4
5
"paste -sd\& -"
- will merge the input lines together, using &
as a separator
paste - merge lines of files
-s, --serial paste one file at a time instead of in parallel
-d, --delimiters=LIST reuse characters from LIST instead of TABs
%fold -w1|paste -sd\& -
1&2&3&4&5
(Note that if the input contains several lines, they'll be joined with &
)
echo "abcdeéèfg" | fold -1 | paste -sd\& -
sed
answers available below. And I don't see any harm in demonstrating how the task can be solved by the other means.
sed 's/\B/\&/g'
\B - Matches everywhere but on a word boundary; that is it matches if the character to the left and the character to the right are either both “word” characters or both “non-word” characters.
Information: GNU sed manual, regular expression extensions.
Testing:
sed 's/\B/\&/g' <<< '12345'
1&2&3&4&5
This will be a little slower than some of the other answers, but it's pretty clear:
echo 12345 | perl -lnE 'say join "&", split //'
Here's another way. The first part of the sed expression captures every character then replaces that with the character and an ampersand. The second part removes the ampersand from the end of the line.
echo 12345 | sed -r 's/(.)/\1\&/g;s/\&$//g'
1&2&3&4&5
Works on multibyte characters too.
sed
twice, a sed
script may have several commands: sed -r 's/(.)/\1\&/g; s/\&$//g'