zsh: no matches found: [:space:] - whitespace

For some reason, in zsh, I'm unable to use the [:space:] pattern to match all whitespace.
ex.
$ echo 'Welcome To Here' | tr [:space:] '\t'
zsh: no matches found: [:space:]
But if I do this in bash, then it works fine
$ echo 'Welcome To Here' | tr [:space:] '\t'
Welcome To Here
Would this be some kind of problem in my ~/.zshrc, or does zsh not support this? I'm also using oh my zsh.

zsh sees the [:space:] and interpets it as a wildcard glob that will match a file named :, s, p, a, c or e. When there are no such files, it produces an error. So will bash with the failglob shell option enabled - your setup presumably turns it off somewhere. Just wrap it in quotes to prevent expansion:
echo 'Welcome To Here' | tr '[:space:]' '\t'

Related

How do I cut everything on each line starting with a multi-character string in bash?

How do I cut everything starting with a given multi-character string using a common shell command?
e.g., given:
foo+=bar
I want:
foo
i.e., cut everything starting with +=
cut doesn't work because it only takes a single-character delimiter, not a multi-character string:
$ echo 'foo+=bar' | cut -d '+=' -f 1
cut: bad delimiter
If I can't use cut, I would consider using perl instead, or if there's another shell command that is more commonly installed.
cut only allows single character delimiter.
You may use bash string manipulation:
s='foo+=bar'
echo "${s%%+=*}"
foo
or use more powerful awk:
awk -F '\\+=' '{print $1}' <<< "$s"
foo
'\\+=' is a regex that matches + followed by = character.
You can use 'sed' command to do this:
string='foo+=bar'
echo ${string} | sed 's/+=.*//g'
foo
or if you're using Bash shell, then use the below parameter expansion (recommended) since it doesn't create unnecessary pipeline and another sed process and so is efficient:
echo ${string%%\+\=*}
or
echo ${string%%[+][=]*}

Unix Shell - Removing special newline characters

We are receiving a file that is delimited into rows with the \(newline) and columns with the \(tab) character.
When there is a manual newline present in one of the "fields" of the file, it comes in as a special newline with two backslashes (\\newline).
To remove the special tabs \(tab), we are using this sed command, which works correctly:
sed "s/$(printf '\\\\\t')/ /g"
The corresponding command for newlines, however does not:
sed "s/$(printf '\\\\\n')/ /g"
It does not remove the \n, only the backslash before it. Is there special handling that needs to be done to remove \(newline)?
Clarification: normal newlines are formatted like this:
\(newline)
Wheras the special characters that need removal are
\\(newline)
Here you go:
echo -e 'hello\\\nthere' | perl -ne 's/\\\n/ /; print'
It would be difficult (but probably possible) to do this in sed, because sed processes input line by line, and your data is broken into multiple lines. This perl one-liner processes the input line by line, and since it treats the newline character as part of the line, it can perform a substitution with space, which I think has the effect that you want.
Or if you prefer awk:
echo -e 'hello\\\nthere' | awk '{ if (gsub(/\\$/, " ")) printf; else print }'
At first I suspected your "special newline" character is just the string \\n like in the output of this command:
echo 'hello\\nthere'
You can replace the string \\n with a space like this:
echo 'hello\\nthere' | sed -e 's/\\\\n/ /g'
You can use tr (translate) command as well to do this, like
tr '\n' ' ' < inputfile.txt
EdIT: In that case use it like
tr '\\\n' ' ' < inputfile.txt

Replace 5 dots with a single space

I have a title that has 5 consecutive dots which I'd like replaced with just one space using bash script. Doing this is not helping:
tr '.....' ' '
Obviously because it's replacing the five dots with 5 spaces.
Basically, I have a title that I want changed to a slug. So I'm using:
tr A-Z a-z | tr '[:punct:] [:blank:]' '-'
to change everything to lowercase and change any punctuation mark and spaces to a hyphen, but I'm stuck with the dots.
The title I'm using is something like: Believe.....Right Now
So I want that turned into believe-right-now
How do I change the 5 dots to a single space?
You don't need sed or awk. Your original tr command should do the trick, you just need to add the -s flag. After tr translates the desired characters into hyphens, -s will squeeze all repeated hyphens into one:
tr A-Z a-z | tr -s '[:punct:] [:blank:]' '-'
I'm not sure what the input/output context is for you, but I tested the above as follows, and it worked for me:
tr A-Z a-z <<< "Believe.....Right Now" | tr -s '[:punct:] [:blank:]' '-'
output:
believe-right-now
See http://www.ss64.com/bash/tr.html for reference.
Transliterations are performed with mappings, which means each character is mapped into something else -- or delete, with tr -d. This is the reason why tr '.....' ' ' does not work.
Replacing five dots with space:
using sed with extended regular expressions:
$ sed -r 's/\.{5}/ /g' <<< "Believe.....Right Now"
Believe Right Now
using sed without -r:
$ sed 's/\.\{5\}/ /g' <<< "Believe.....Right Now"
Believe Right Now
using parameter expansion:
$ text="foo.....bar.....zzz" && echo "${text//...../ }"
foo bar zzz
Replacing five dots and spaces with -:
$ sed -r 's/\.{5}| /-/g' <<< "Believe.....Right Now"
Believe-Right-Now
Full replacement -- ditching tr usage:
$ sed -re 's/\.{5}| /-/g' -e 's/([A-Z])/\l&/g' <<< "Believe.....Right Now"
believe-right-now
or, in case your sed version does not support the flag -r, you may use:
$ sed -e 's/\.\{5\}\| /-/g' -e 's/\([A-Z]\)/\l&/g' <<< "Believe.....Right Now"
believe-right-now
$ cat file
Believe.....Right Now
$ awk '{gsub(/[[:punct:][:space:].]+/,"-"); print tolower($0)}' file
believe-right-now

bash script tr -d [:punct:] does not work

This command isn't work on my laptop how I'd expect it to since it doesn't remove the punctuation characters.
echo "asdaftafiatfiat!!!~~~$$$$tt" | tr -d [:punct:]
However tr -d [:punct:] remove t from the string.
It's a quoting issues, your shell is interpreting $ and ! because you are using double quotes. You need to use single quotes to avoid any character being interpreted with bash:
$ echo 'asdaftafiatfiat!!!~~~$$$$tt' | tr -d [:punct:]
asdaftafiatfiattt
I think your tr doesn't recognize classes like [:punct:], but try quoting it perhaps:
... | tr -d '[:punct:]'
If you find difficulty with bash's history expansion you can disable it:
shopt -u -o histexpand
echo 'asdaftafiatfiat!!!~~~$$$$tt' | tr -d '[:punct:]'

escaping newlines in sed replacement string

Here are my attempts to replace a b character with a newline using sed while running bash
$> echo 'abc' | sed 's/b/\n/'
anc
no, that's not it
$> echo 'abc' | sed 's/b/\\n/'
a\nc
no, that's not it either. The output I want is
a
c
HELP!
Looks like you are on BSD or Solaris. Try this:
[jaypal:~/Temp] echo 'abc' | sed 's/b/\
> /'
a
c
Add a black slash and hit enter and complete your sed statement.
$ echo 'abc' | sed 's/b/\'$'\n''/'
a
c
In Bash, $'\n' expands to a single quoted newline character (see "QUOTING" section of man bash). The three strings are concatenated before being passed into sed as an argument. Sed requires that the newline character be escaped, hence the first backslash in the code I pasted.
You didn't say you want to globally replace all b. If yes, you want tr instead:
$ echo abcbd | tr b $'\n'
a
c
d
Works for me on Solaris 5.8 and bash 2.03
In a multiline file I had to pipe through tr on both sides of sed, like so:
echo "$FILE_CONTENTS" | \
tr '\n' ¥ | tr ' ' ∑ | mySedFunction $1 | tr ¥ '\n' | tr ∑ ' '
See unix likes to strip out newlines and extra leading spaces and all sorts of things, because I guess that seemed like the thing to do at the time when it was made back in the 1900s. Anyway, this method I show above solves the problem 100%. Wish I would have seen someone post this somewhere because it would have saved me about three hours of my life.
echo 'abc' | sed 's/b/\'\n'/'
you are missing '' around \n

Resources