Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I got a string like the following:

test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

now I want to replace all the tabs/spaces inbetween the records with just a single space so I can easily use it with cut -d " "

I tried the following:

sed "s/[\t[:space:]]+/[:space:]/g"

and various varions but couldn't get it working. Any ideas?

share|improve this question
    
Try: sed -r -e "s/[\t\ ]+/ /g" –  RJS Sep 23 '12 at 18:28
    
Does your cut supports -w option? –  Kondybas Aug 17 at 9:10

1 Answer 1

up vote 6 down vote accepted

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"

share|improve this answer
    
Does this remove tabs too? Can you explain why you use \+ instead of just +? –  Zulakis Sep 23 '12 at 18:27
    
Okay, I understand. [[:space:]] is equal to [ \t\r\n\v\f]. But can you please explain why you use \+ –  Zulakis Sep 23 '12 at 18:47
3  
[[:space:]] is equivalent to '\s', so the shorter version is "s/\s\+/ /g" –  3molo Sep 23 '12 at 18:47
1  
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/…. –  3molo Sep 23 '12 at 18:51
    
Ahh, I understand! I did not know that there were different regex versions. Thanks –  Zulakis Sep 23 '12 at 18:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.