# bash expanding to same value instead of line by line value in sed command

I have a file containing numbers in it say numbers.txt as follows.

9374541632553
51243747879841
32030098896914
84654557358238
11000656847765


I want to convert it to the following format.

<item>9 3 7 4 5 4 1 6 3 2 5 5 3 <tag>out="9374541632553"
<item>5 1 2 4 3 7 4 7 8 7 9 8 4 1 <tag>out="51243747879841"
<item>3 2 0 3 0 0 9 8 8 9 6 9 1 4 <tag>out="32030098896914"
<item>8 4 6 5 4 5 5 7 3 5 8 2 3 8 <tag>out="84654557358238"
<item>1 1 0 0 0 6 5 6 8 4 7 7 6 5 <tag>out="11000656847765"


I'am using following command to convert it.

cat numbers.txt | while read line; do sed -r "s/([0-9])/\1/g; s/([0-9])/\1 /g ; s/^/<item>/g; s/$/<tag>out="\$line/g" ; done


But output I'am getting is as follows:

<item>5 1 2 4 3 7 4 7 8 7 9 8 4 1 <tag>out="9374541632553
<item>3 2 0 3 0 0 9 8 8 9 6 9 1 4 <tag>out="9374541632553
<item>8 4 6 5 4 5 5 7 3 5 8 2 3 8 <tag>out="9374541632553
<item>1 1 0 0 0 6 5 6 8 4 7 7 6 5 <tag>out="9374541632553
<item>3 3 2 1 6 7 8 2 0 9 3 8 4 2 <tag>out="9374541632553


Anyone can you please tell me why only 1st line is getting printed at last column instead of line by line value.
And what about 1st line in output?
Explain the required command to desired output.

You can do it without loop in awk:

awk '{a=$1;gsub(/./,"& ",$1); print "<item>"$1"<tag><out>=""\""a"\""}' numbers.txt  Output: <item>9 3 7 4 5 4 1 6 3 2 5 5 3 <tag><out>="9374541632553" <item>5 1 2 4 3 7 4 7 8 7 9 8 4 1 <tag><out>="51243747879841" <item>3 2 0 3 0 0 9 8 8 9 6 9 1 4 <tag><out>="32030098896914" <item>8 4 6 5 4 5 5 7 3 5 8 2 3 8 <tag><out>="84654557358238" <item>1 1 0 0 0 6 5 6 8 4 7 7 6 5 <tag><out>="11000656847765"  Explanation: • first we store first field $1 in variable a
• substitute each character in $1 with itself followed by space • and finally print everything in desired order. • a little tricky part is printing double quotes where \" should be quoted itself Edit (removing last space): awk '{a=$1;gsub(/./,"& ",$1); printf "<item>"$1"\b<tag><out>=""\""a"\"\n"}' numbers.txt

<item>9 3 7 4 5 4 1 6 3 2 5 5 3<tag><out>="9374541632553"
<item>5 1 2 4 3 7 4 7 8 7 9 8 4 1<tag><out>="51243747879841"
<item>3 2 0 3 0 0 9 8 8 9 6 9 1 4<tag><out>="32030098896914"
<item>8 4 6 5 4 5 5 7 3 5 8 2 3 8<tag><out>="84654557358238"
<item>1 1 0 0 0 6 5 6 8 4 7 7 6 5<tag><out>="11000656847765"

• can u please explain the above awk command ....I mean how it works – AVJ Jul 31 '15 at 4:57
• what if we want to remove space between last number and word '<tag><out>' – AVJ Jul 31 '15 at 10:20
• @AVJ see the edit for explanation, to remove last space just use printf instead of print and hit backspace \b. – jimmij Jul 31 '15 at 10:45

Because both read and sed are taking data from stdin.

In the while loop, you read the first line into $line. Then sed starts: you don't give it any other input so it reads from stdin, which is the output of cat numbers.txt. So sed will consume the rest of the input. And since you're still in the first iteration of the while loop, the$line variable doesn't change

I'd use perl for this:

perl -lne '($spaced =$_) =~ s/./$& /g; print qq{<item>$spaced<tag>out="$_"}' numbers.txt  • thanks for your explanation.. it helped me to understand...Also by your command i can achieve desired output. – AVJ Jul 31 '15 at 4:55 Here's one way you might be able to do the whole thing in sed: sed ' h; s/./& /g; s/.*/<item>&<tag>out=/; G; s/\n$$[0-9]*$$/"\1"/; ' numbers.txt  • Removing regexp speed up script more then 25% h; s/./& /g; s/^/<item>/; G; s/\n$$.*$$/<tag>out="\1"/ – Costas Jul 30 '15 at 21:08 I would think the quickest way to do it would look something like... sed -e's/./& /g;i\' -e'<item>' \ -ea\\ -e'<tag><out>=' <file | paste -d'\0 ""' - - - ./file /dev/null  This also works: ( set -- - - - - - - /tmp/file paste -d'<item> <tag><out>="' "$@" - - - - - - "$@" | sed 's/ *$/"/;s/$$[0-9]$$ *$$<.*$$*/\1 \2/g'
)       </dev/null


cat numbers.txt | while read line; do echo $line | sed -r "s/([0-9])/\1/g; s/([0-9])/\1 /g ; s/^/<item>/g; s/$/<tag>out=\"$line\"/g" ; done  Or, cat numbers.txt | while read line; do echo "<item>$(echo $line | fold -w1 | paste -s -d' ') <tag>out=\"$line\""; done