LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-15-2015, 02:42 PM   #1
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
Replace a string of blanks with a "tailored" string of equal length


It is desired to replace strings of 3 or more blanks with "tailored" strings of equal length, such that the replacement string has one leading blank, one trailing blank, and all the interior characters are "%".

InFile ...
Code:
cat dog
red   blue  green
   apple     pear
 honda toyota         nissan
Desired OutFile...
Code:
cat dog
red % blue  green
 % apple %%% pear
 honda toyota %%%%%%% nissan
A sed or awk solution is preferred.

Daniel B. Martin
 
Old 10-15-2015, 05:53 PM   #2
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Original Poster
Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
I hammered out a sed solution. It looks clumsy (3 steps) but works.

Step 1) Replace all blanks with %.
Step 2) Replace the leading character in a string of %s with a blank.
Step 3) Replace the trailing character in a string of %s with a blank.

With this InFile ...
Code:
cat dog
red   blue  green
   apple     pear
 honda toyota         nissan
... this sed ...
Code:
sed 's/ /%/g;s/\([^%]\)%%/\1 %/g;s/%\([^%]\)/ \1/g' $InFile >$OutFile
... produced this OutFile ...
Code:
cat dog
red % blue  green
%% apple %%% pear
 honda toyota %%%%%%% nissan
Shorter and cleaner solutions are welcomed!

Daniel B. Martin
 
Old 10-15-2015, 07:12 PM   #3
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Isn't your OutFile missing a space at the beginning of the third line?

Anyway, my first attempt would be

Code:
sed 's/\B \B//g'
In this case, the initial whitespace is also missing. That can be fixed with an aditional substitution:

Code:
sed 's/\B \B/%/g;s/^%/ /'
And a (not very nice) gawk solution:

Code:
awk -F'(^ | \\<)|(\\> | $)' '{for (i=1;i<NF;i++)gsub(/ /,"%",$i);print}'
 
1 members found this post helpful.
Old 10-15-2015, 09:50 PM   #4
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Original Poster
Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
Quote:
Originally Posted by millgates View Post
Isn't your OutFile missing a space at the beginning of the third line?
Yes. My proposed solution has a flaw.

Code:
sed 's/\B \B//g'
This plugs in no %s at all. Presumably you meant ...
Code:
sed 's/\B \B/%/g' $InFile >$OutFile
This sed is lovely!
Code:
sed 's/\B \B/%/g;s/^%/ /'
After making the original post I devised a debugging aid. It prints one line from InFile, the corresponding line from OutFile, and then a blank line, repeat, repeat.
Code:
paste -d "\n" $InFile $OutFile /dev/null
With this InFile ...
Code:
cat dog
red   blue  green
   apple     pear
 honda toyota         nissan
... this code ...
Code:
echo; echo "Method #2 of LQ Member millgates."
sed 's/\B \B/%/g;s/^%/ /' $InFile >$OutFile

# This PASTE interleaves three files.
# The third file (/dev/null) contains empty lines.
echo
paste -d "\n" $InFile $OutFile /dev/null
... produces this display ...
Code:
Method #2 of LQ Member millgates.

cat dog
cat dog

red   blue  green
red % blue  green

   apple     pear
 % apple %%% pear

 honda toyota         nissan
 honda toyota %%%%%%% nissan
Looks good! Thanks!

Daniel B. Martin
 
Old 10-16-2015, 06:41 AM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
For the awk I would probably follow the same solution as millgates has for sed:
Code:
awk 'gsub(/\B \B/,"") && sub(/^%/," ") || 1'
I did knock up a ruby solution, just to do it a different way from the regex solution:
Code:
ruby -pe '$_.chomp.scan(/ {3,}/){|n| $_.sub!(n, " #{n[1..-2].gsub(/ /,"%")} ")}'
 
1 members found this post helpful.
Old 10-16-2015, 07:30 AM   #6
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Original Poster
Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
[QUOTE=grail;5435496]
Code:
awk 'gsub(/\B \B/,"") && sub(/^/," ") || 1'
This didn't work until I remembered something from a recent unrelated post. Single percent signs sometimes vanish from posts. That explains why a sed solution posted by millgates seemed to fail, and also why your awk seemed to fail. Thanks to both of you for constructive and instructive solutions.

Daniel B. Martin

Last edited by danielbmartin; 10-16-2015 at 07:31 AM. Reason: Cosmetic improvement
 
Old 10-16-2015, 11:07 AM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Yes sorry about that, I will remember one day
 
  


Reply

Tags
awk, sed, text processing



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
reg expr: match a string A-Z, a-z, * or a blank ( but string can not be all blanks) matt007 Programming 4 12-22-2009 08:55 AM
[perl]How to treat string like "a b" as a single string when split? john.daker Programming 21 06-01-2009 05:57 PM
Error while installing PostFix "bad string length" shorto Linux - Server 5 04-20-2008 09:14 PM
output the path for files whose names include string "string" (case insensitive) sean_zhang Linux - Newbie 1 03-04-2008 11:59 PM
Shell script: Find "\n\t..." to replace a string in a file michael24h7d Programming 8 05-11-2007 03:07 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:52 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration