'Regex for line containing one or more spaces or dashes

I got .txt file with city names, each in separate line. Some of them are few words with one or multiple spaces or words connected with '-'. I need to create bash command which will echo those lines out. Currently I'm using cat piped with grep but I can't get both spaces and dash into one search and I had problems with checking for multiple spaces.

print lines with dash:
cat file.txt | grep ".*-.*"

print lines with spaces:
cat file.txt | grep ".*\s.*"

tho when I try to do:
cat file.txt | grep ".*\s+.*"
I get nothing.

Thanks for help



Solution 1:[1]

This does not directly address your question, but is too much to put in a comment.

You don't need the .* in your patterns. .* at the beginning or end of a pattern is useless, because it means "0 or more of any character" and so will always match.

These lines are all identical:

cat file.txt | grep ".*-.*"
cat file.txt | grep "-.*"
cat file.txt | grep "-"

Plus you don't need to cat and pipe:

grep "-" file.txt

Solution 2:[2]

When grep pattern matches, the default action is to print the whole line, so .* in all your patterns are redundant, you may delete them. Also, you don't have to use cat file | as you may specify the file to grep directly after pattern, i.e. grep 'pattern' file.txt.

Here are some more details:

  • grep ".*-.*" = grep -- "-" - returns any lines having a - char (-- singals the end of options, the next thing is the pattern)
  • grep ".*\s.*" = grep "\s" - matches and returns lines containing a whitespace char (only GNU grep)
  • grep ".*\s+.*" = grep "\s+" - returns line containing a whitespace followed with a literal + char (since you are using POSIX BRE regex here the unescaped + matches a literal plus symbol).

You want

grep "[[:space:]-]" file.txt

See the online demo:

#!/bin/bash
s='abc - def
ghi
jkl mno'
grep '[[:space:]-]' <<< "$s"

Output:

abc - def
jkl mno

The [[:space:]-] POSIX BRE and ERE (enabled with -E option) compliant pattern matches either any whitespace (with the [:space:] POSIX character class) or a hyphen.

Note that [\s-] won't work since \s inside a bracket expression is not treated as a regex escape sequence but as a mere \ or s.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Andy Lester
Solution 2 Wiktor Stribiżew