sed replace all tabs and spaces with a single space

185

Solution 1

Use sed -e "s/[[:space:]]\+/ /g"

Here's an explanation:

[   # start of character class

  [:space:]  # The POSIX character class for whitespace characters. It's
             # functionally identical to [ \t\r\n\v\f] which matches a space,
             # tab, carriage return, newline, vertical tab, or form feed. See
             # https://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes

]   # end of character class

\+  # one or more of the previous item (anything matched in the brackets).

For your replacement, you only want to insert a space. [:space:] won't work there since that's an abbreviation for a character class and the regex engine wouldn't know what character to put there.

The + must be escaped in the regex because with sed's regex engine + is a normal character whereas \+ is a metacharacter for 'one or more'. On page 86 of Mastering Regular Expressions, Jeffrey Friedl mentions in a footnote that ed and grep used escaped parentheses because "Ken Thompson felt regular expressions would be used to work primarily with C code, where needing to match raw parentheses would be more common than backreferencing." I assume that he felt the same way about the plus sign, hence the need to escape it to use it as a metacharacter. It's easy to get tripped up by this.

In sed you'll need to escape +, ?, |, (, and ). or use -r to use extended regex (then it looks like sed -r -e "s/[[:space:]]\+/ /g" or sed -re "s/[[:space:]]\+/ /g"

Solution 2

You can use the -s ("squeeze") option of tr:

$ tr -s '[:blank:]' <<< 'test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600'
test.de. 1547 IN SOA ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

The [:blank:] character class comprises both spaces and tabs.

Share:
185

Related videos on Youtube

Premt
Author by

Premt

Updated on September 18, 2022

Comments

  • Premt
    Premt almost 2 years

    Hi guy's i got this math equation to movement the enemy x,y,z but i can't seem to replicate the result i want once am done with x,y i wanna create z movement also

    So let's say i have a enemy with the movement speed of 1.5 his position is

    Enemy Position: posX > 119.75013, posY > 12.1830482, posZ > 167.700226
    

    I want to move him to

    Enemy Final Position: posX > 119.41893, posY > 11.3724937, posZ > 162.9639
    

    With these x,y,z result:

    Enemy movement: posX > 119.645088, posY > 11.9535465, posZ > 166.198029
    Enemy movement: posX > 119.539749, posY > 11.7193651, posZ > 164.691589
    Enemy movement: posX > 119.479477, posY > 11.54633, posZ > 163.829742
    

    But the function only prints

    Enemy Movement: posX 119.182753804649, posY 10.7944934646909
    

    Note i am not using Unity3D so i need a function that works with out unity3d..

    Current function:

    static void Main(string[] args)
    {
        double startX = 119.75013;
        double startY = 12.1830482;
        double startZ = 167.700226;
    
        double x = 119.41893;
        double y = 11.3724937;
        double z = 162.9639;
    
        double endX = x;
        double endY = y;
        double endZ = y;
    
        double speed = 1.5f;
    
        Console.WriteLine($"Enemy Position: posX {startX}, posY {startY}, posZ {startZ}");
        Console.WriteLine($"Enemy Final Position: posX {x}, posY {y}, posZ {z}\n");
    
        double distance = Math.Sqrt(Math.Pow(endX - startX, 2) + Math.Pow(endY - startY, 2));
        double directionX = (endX - startX) / distance;
        double directionY = (endY - startY) / distance;
    
    
        double newlat = startX;
        double newLng = startY;
    
    
        while (Math.Sqrt(Math.Pow(newlat - startX, 2) + Math.Pow(newLng - startY, 2)) <= distance)
        {
    
            newlat += directionX * speed;
            newLng += directionY * speed;
    
            Console.WriteLine($"Enemy Movement: posX {newlat}, posY {newLng}");
        }
    
        Console.ReadKey();
    }
    

    Thank you!

    • RJS
      RJS almost 12 years
      Try: sed -r -e "s/[\t\ ]+/ /g"
    • rory.ap
      rory.ap about 7 years
      This question will be closed as off topic unless you can improve it. . Questions which ask "why isn't this code working" are off topic unless they contain more information. Please go to How to Ask and help center.
    • Premt
      Premt about 7 years
      Okay edited ty.
    • Jeroen van Langen
      Jeroen van Langen about 7 years
      There is no z movement in your code. So the z won't be affected
    • Premt
      Premt about 7 years
      I know z won't be effected i need to get the results of x,y right first to make the z .
    • Franck
      Franck about 7 years
      If you don't want to use Unity i highly suggest you check out System.Windows.Media.Media3D namespace. Point3D and Vector3D can do most of the work.
  • Zulakis
    Zulakis almost 12 years
    Does this remove tabs too? Can you explain why you use \+ instead of just +?
  • Zulakis
    Zulakis almost 12 years
    Okay, I understand. [[:space:]] is equal to [ \t\r\n\v\f]. But can you please explain why you use \+
  • SiXoS
    SiXoS almost 12 years
    [[:space:]] is equivalent to '\s', so the shorter version is "s/\s\+/ /g"
  • SiXoS
    SiXoS almost 12 years
    Basic regular expressions use a backslash prior to a plus sign when used to mean “one or more of the previous character or group”, source developer.apple.com/library/mac/#documentation/opensource/….
  • Zulakis
    Zulakis almost 12 years
    Ahh, I understand! I did not know that there were different regex versions. Thanks
  • Jeroen van Langen
    Jeroen van Langen about 7 years
    You must change the newlat - startX to endX - newlat Same for newLng - startY to endY - newLng You're subtracting the old value from the new value. But instead you still want the delta between te new position and the endpoint. You should use the Vector3 types/math. way easier..
  • Premt
    Premt about 7 years
    Don't really get how i can apply this to my code can you apply it so i understand?
  • Aziuth
    Aziuth about 7 years
    @Premt You... exchange double speed = 1.5f; with double speed = 0.25f;. But please, do not use code that you don't understand!
  • Læti
    Læti about 7 years
    How does this answers the question?
  • UpAndAdam
    UpAndAdam over 4 years
    This seems wrong. at least on OSX I have to do `sed -E "s/[[:space:]]+/ /g" when we go to extended you dont need to escape the + sign for multiplicity anymore.