6

In Linux, if I have a file with entries like:

My Number is = 1234; #This is a random number

Can I use sed or anything else to replace all spaces after '#' with '+', so that the output looks like:

My Number is = 1234; #This+is+a+random+number

user1536435
  • 129
  • 8

5 Answers5

3

One way using awk:

awk -F# 'OFS=FS { gsub(" ", "+", $2) }1' file.txt

Result:

My Number is = 1234; #This+is+a+random+number

EDIT:

After reading comments below, if your file contains multiple #, you can try this:

awk -F# 'OFS=FS { for (i=2; i <= NF; i++) gsub(" ", "+", $i); print }' file.txt
Steve
  • 51,466
  • 13
  • 89
  • 103
  • 1
    The `1` is an expression that evaluates to true, causing the current line to be printed. It's a short-cut for `{print}`. – ghoti Jul 19 '12 at 01:04
  • While this answer is a nice example of awk, I'm not 100% sure it meets the OP's requirements. What if there is another `#` in the line? – ghoti Jul 19 '12 at 01:06
  • replace `gsub(" ", "+", $2)` with `for (i=2;i<=NF;++i) gsub(" ", "+", $i)` and it will handle any number of `#` chars – Mark Reed Jul 19 '12 at 01:09
  • Also, the `1` trick is nice for code golf, but in general I think a simple `; print` inside the curlies would be clearer. – Mark Reed Jul 19 '12 at 01:09
  • @ghoti, Point noted. I made some assumptions about the OP's input. – Steve Jul 19 '12 at 01:15
  • @MarkReed, Yes a `for` loop as you describe would fix it. I will update my answer. – Steve Jul 19 '12 at 01:16
3

You can do this in pure shell...

$ foo="My Number is = 1234; #This is a random number"
$ echo -n "${foo%%#*}#"; echo "${foo#*#}" | tr ' ' '+'
My Number is = 1234; #This+is+a+random+number
$ 

Capturing this data to variables for further use is left as an exercise for the reader. :-)

Note that this also withstands multiple # characters on the line:

$ foo="My Number is = 1234; #This is a # random number"
$ echo -n "${foo%%#*}#"; echo "${foo#*#}" | tr ' ' '+'
My Number is = 1234; #This+is+a+#+random+number
$ 

Or if you'd prefer to create a variable rather than pipe through tr:

$ echo -n "${foo%%#*}#"; bar="${foo#*#}"; echo "${bar// /+}"
My Number is = 1234; #This+is+a+#+random+number

And finally, if you don't mind subshells with pipes, you could do this:

$ bar=$(echo -n "$foo" | tr '#' '\n' | sed -ne '2,$s/ /+/g;p' | tr '\n' '#')
$ echo "$bar"
My Number is = 1234; #This+is+a+#+random+number
$

And for the fun of it, here's a short awk solution:

$ echo $foo | awk -vRS=# -vORS=# 'NR>1 {gsub(/ /,"+")} 1'
My Number is = 1234; #This+is+a+#+random+number
#$ 

Note the trailing ORS. I don't know if it's possible to avoid a final record separator. I suppose you could get rid of that by piping the line above through head -1, assuming you're only dealing with the one line of input data.

ghoti
  • 45,319
  • 8
  • 65
  • 104
2

Not terrible efficient, but:

perl -pe '1 while (s/(.*#[^ ]*) /\1+/);'
Seth Robertson
  • 30,608
  • 7
  • 64
  • 57
2

This might work for you (GNU sed):

echo 'My Number is = 1234; #This is a random number' | 
sed 's/#/\n&/;h;s/.*\n//;y/ /+/;H;g;s/\n.*\n//'
My Number is = 1234; #This+is+a+random+number
potong
  • 55,640
  • 6
  • 51
  • 83
  • 1
    **+1** - Great, I was hoping somebody would demonstrate this with a hold buffer. :) Alas, in BSD sed it breaks badly if there's a second `#` on the line. (But you did mention GNU, so you keep your +1!) – ghoti Jul 20 '12 at 01:10
  • @ghoti thanks, I'm surprised that a second `#` causes a problem (even for BSD). Usually the `\n`'s are the ones at fault in other sed's. Could you have added a `g` to the substitute command in translation? – potong Jul 20 '12 at 06:34
1

Here is yet another perl one-liner:

echo 'My Number is = 1234; #This is a random number' \
| perl -F\# -lane 'join "#", @F[1,-1]; s/ /+/g; print $F[1], "#", $_'
  • -F specifies how to split string into @F array.
  • -an wraps stdin with:
while (<>) {
  @F = split('#');
  # code from -e goes here
}
Thor
  • 45,082
  • 11
  • 119
  • 130
  • It also breaks if there are extra `#` characters. Try it with: `'My Number is = 1234; #This is a random # number` to see. – Graham Jul 19 '12 at 03:58
  • Right forgot about the separator, will fix it shortly. – Thor Jul 19 '12 at 08:00
  • The fix maintains the first separator, but still doesn't help with the alternate string I posted. – Graham Jul 19 '12 at 11:05