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

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:]'

Related

zsh: no matches found: [:space:]

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'

How to grep all characters in file

I have a CSV file with this lines:
----------+79975532211,----------+79975532212
4995876655,4995876658
I try to grep this lines in Bash script
#!/bin/bash
config='/test/config.conf'
sourcecsv=/test/sourse.csv
cat $sourcecsv | while read line
do
Oldnumber=$(echo $line | cut -d',' -f1)
cat $config | grep "\\$Oldnumber" -B 8
done
But when script grep value 4995876655 I get error:
grep: Invalid back reference
How I can grep all values in my file?
Instead of:
cat $config | grep "\\$Oldnumber" -B 8
You should do:
grep -B 8 -F -- "$Oldnumber" "$config"
If you really mean to grep for all strings between commas, you can do it all in one go.
tr ',' '\n' </test/sourse.csv |
grep -F -f - -B 8 /test/config.conf
If you need to obtain the matches in sequence (all matches for the first string followed by all matches for the second, etc) then maybe loop over them with a proper while loop:
tr ',' '\n' </test/sourse.csv |
while read -r Oldnumber; do
grep -F -B 8 -e "$Oldnumber" /test/config.conf
done
Keeping the file names in variables does not seem to offer any advantage here.
If you mean to search for the strings preceded by a literal backslash, you can add it back; the -F option I added turns all strings into literals. If you need metacharacters, and take out the -F option, you need to double the backslashes (inside double quotes, a single backslash needs to be represented as double; and to get a literal backslash in a regular expression, you need two of them).

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

Split string by newline and space in Bourne shell

I'm currently using the following to split a file into words - Is there some quicker way?
while read -r line
do
for word in $line
do
words="${words}\n${word}"
done
done
What about using tr?
tr -s '[:space:]' '\n' < myfile.txt
The -s squeezes multiple whitespace characters into one.
xargs -n 1 echo <myfile.txt
sed 's/[[:space:]]/\n/g' file.txt

How to extract and chop version string from file in bash

I have a simple text file ./version containing a version number. Unfortunately, sometimes the version number in the file is followed by whitespaces and newlines like
1.1.3[space][space][newline]
[newline]
[newline]
What is the best, easiest and shortest way to extract the version number into a bash variable without the trailing spaces and newlines? I tried
var=`cat ./version | tr -d ' '`
which works for the whitespaces but when appending a tr -d '\n' it does not work.
Thanks,
Chris
$ echo -e "1.1.1 \n\n" > ./version
$ read var < ./version
$ echo -n "$var" | od -a
0000000 1 . 1 . 1
0000005
Pure Bash, no other process:
echo -e "1.2.3 \n\n" > .version
version=$(<.version)
version=${version// /}
echo "'$version'"
result: '1.2.3'
I still do not know why, but after deleting and recreating the version file this worked:
var=`cat ./version | tr -d ' ' | tr -d '\n'`
I'm confused... what can you do different when creating a text file. However, it works now.
I like the pure bash version from fgm's answer.
I provide this one-line perl command to remove also other characters if any:
perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
The extracted version number is trimmed/stripped (no newline or carriage return symbols):
$> V=$( bash --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' )
$> echo "The bash version is '$V'"
The bash version is '4.2.45'
I provide more explanation and give other more sophisticated (but still short) one-line perl commands in my other answer.

Resources