This question already has answers here:
Extract substring in Bash
(26 answers)
Closed 9 years ago.
we were trying to find the username of a mercurial url:
default = ssh://someone#acme.com//srv/hg/repo
Suppose that there's always a username, I came up with:
tmp=${a#*//}
user=${tmp%%#*}
Is there a way to do this in one line?
Assuming your string is in a variable like this:
url='default = ssh://someone#acme.com//srv/hg/repo'
You can do:
[[ $url =~ //([^#]*)# ]]
Then your username is here:
echo ${BASH_REMATCH[1]}
This works in Bash versions 3.2 and higher.
You pretty much need more that one statement or to call out to external tools. I think sed is best for this.
sed -r -e 's|.*://(.*)#.*|\1|' <<< "$default"
Not within bash itself. You'd have to delegate to an external tool such as sed.
Not familiar with mercurial, but using your url, you can do
echo 'ssh://someone#acme.com/srv/hg/repo' |grep -E --only-matching '\w+#' |cut --delimiter=\# -f 1
Probably not the most efficient way with the two pipes, but works.
Related
This question already has answers here:
Bash function to find newest file matching pattern
(9 answers)
Closed 2 years ago.
I'm trying to do a bash one liner to get the latest logfile to cat and/or tail:
for i in /mnt/usbdrive/backup/filelog_*.log; do ls -t $i | head -n1 ; done
But get all of the matching files:
/mnt/usbdrive/backup/filelog_2020-06-03-09:00:01:345123169.log
/mnt/usbdrive/backup/filelog_2020-06-04-09:00:01:370667894.log
/mnt/usbdrive/backup/filelog_2020-06-04-19:15:27:274135912.log
/mnt/usbdrive/backup/filelog_2020-06-05-09:00:02:020131150.log
/mnt/usbdrive/backup/filelog_2020-06-06-09:00:02:238963148.log
Where am I going wrong?
Also, if I wanted to tail (or cat) that, would I have to declare another variable and tail -f that $variable ?
I'm trying to do a bash one liner to get the latest logfile
You could use
latestfile=$(/bin/ls -t /mnt/usbdrive/backup/filelog_*.log | /bin/tail -1)
assuming you don't have spaces (or semicolons, etc...) in your file names
See ls(1), tail(1) and carefully read the documentation of GNU bash.
You'll better write your script in some other language (e.g. GNU guile, Python, Lua). See the shebang handling of execve(2).
You might also use stat(1) and/or gawk(1) and/or find(1). See glob(7) and path_resolution(7).
You could be interested by logrotate(8) and crontab(5) and inotify(7).
This question already has answers here:
How to grep asterisk without escaping?
(2 answers)
When to wrap quotes around a shell variable?
(5 answers)
Closed 3 years ago.
I am trying to come up with a function that searches a given file for a given pattern. If the pattern is not found it shall be appended to the file.
This works fine for some cases, but when my pattern includes special characters, like wildcards (*) this method fails.
Patterns that work:
pattern="some normal string"
Patterns that don't work:
pattern='#include "/path/to/dir/\*.conf"'
This is my function:
check_pattern() {
if ! grep -q "$1" $2
then
echo $1 >> $2
fi
}
I' calling my function like this:
check_pattern $pattern $target_file
When escaping the wildcard in my pattern variable to get grep running correctly echo interprets the \ as character.
So when I run my script a second time my grep does not find the pattern and appends it again.
To put it simple:
Stuff that gets appended:
#include "/path/to/dir/\*.conf"
Stuff that i want to have appended:
#include "/path/to/dir/*.conf"
Is there some way to get my expected result without storing my echo-pattern in a second variable?
Use
grep -f
and
check_pattern "$pattern" "$target_file"
Thanks all, I got it now.
Using grep -F as pointed out by Gem Taylor in combination with calling my function like this check_pattern "$pattern" "$target_file" did the tricks.
This question already has answers here:
How to check if a files exists in a specific directory in a bash script?
(3 answers)
Closed 4 years ago.
I'm not sure how to word my question exactly...
I have the code
if grep "mynamefolder" /vol/Homefs/
then
echo "yup"
else
echo "nope"
fi
which gives me the output
grep: /vol/Homefs/: Is a directory
nope
The sh file containing the code and the directory I'm targeting are not in the same directory (if that makes sense).
I want to find the words myfoldername inside /vol/Homefs/ without going through any subdirectories. Doing grep -d skip, which I hoped would "skip" subdirectories and focus only directories, just gives me nope even though the folder/file/word I'm testing it on does exist.
Edit: I forgot to mention that I would also like mynamefolder to be a variable that I can write in putty, something like
./file spaing and spaing being the replacement for myfoldername.
I'm not sure if I did good enough explaining, let me know!
You just want
if [ -e /vol/Homefs/"$1" ]; then
echo yup
else
echo nope
fi
The [ command, with the -e operator, tests if the named file entry exists.
vim is not involved, and grep is not needed.
If you're insisting on using grep, you should know grep doesn't work on directories. You can convert the directory listing to a string.
echo /vol/Homefs/* | grep mynamefolder
This question already has answers here:
Remove/replace html tags in bash
(2 answers)
Closed 6 years ago.
I've been trying to convert the following string into a more readable and usable form in a bash script. Certain parts are not static.
(<font color='whisper'>[ <name shortname='UserName' src='whisper-from'>UserName</name> whispers, "test" to you. ]</font>
A lot of the stuff in fact is not static. Basically, I want the end result to look like:
([UserName whispers, "test" to you. ]
I have done this time and time again in Java, PHP, and even VB6. However I am new to bash scripts, and can't seem to get it to work.
Could someone help me convert this Java code to bash script?
data = MyString.replaceAll("<.*?>", "");
data = MyString.replaceAll("<", "<");
data = MyString.replaceAll(">", ">");
In bash, you can use pattern substitution. Let's start with this string:
$ s='<Name>'
And, let's do substitutions on it:
$ s="${s//</<}"
$ s="${s//>/>}"
$ echo "$s"
<Name>
Bash works on globs. If you need regular expressions, try sed:
$ s='<Name>'
$ echo "$s" | sed 's/</</g; s/>/>/g; s/<[^>]*>/<>/g'
<>
In a more complex example:
$ MyStr='(<font color='whisper'>[ <name shortname='UserName' src='whisper-from'>UserName</name> whispers, "test" to you. ]</font>'
$ echo "$MyStr" | sed 's/</</g; s/>/>/g; s/<[^>]*>//g'
([ UserName whispers, "test" to you. ]
Use sed by itself or, since you mentioned bash, use sed within a bash script (for example b.sh):
#!/bin/bash
sed 's/>/>/g' | sed 's/</</g' | sed 's/<.*?>//g'
Input data (for example b.txt file):
asdasdasdds<.*?>dasdasassxrh
sadaswqqw<ssadasdasdsdvvxc
sadssadadsads>dsdsdewpppp
Output results:
asdasdasddsdasdasassxrh
sadaswqqw<ssadasdasdsdvvxc
sadssadadsads>dsdsdewpppp
Usage:
b.sh < b.txt
NOTE: I broke each replace all into separate sed calls in case you wanted to modify or add more formatting changes.
This question already has answers here:
Forcing bash to expand variables in a string loaded from a file
(13 answers)
Closed 7 years ago.
Let's say I have a file called path.txt containing the text $HOME/filedump/ on a single line. How can I then read the contents of path.txt into a variable, while having Bash parse said content?
Here's an example of what I'm trying to do:
#!/bin/bash
targetfile="path.txt"
target=$( [[ -f $targetfile ]] && echo $( < $targetfile ) || echo "Not set" )
echo $target
Desired output: /home/joe/filedump/
Actual output: $HOME/filedump/
I've tried using cat in place of <, wrapping it in quotes, and more. Nothing seems to get me anywhere.
I'm sure I'm missing something obvious, and there's probably a simple builtin command. All I can find on Google is pages about reading variables from ini/config files or splitting one string into multiple variables.
If you want to evaluate the contents of path.txt and assign that to target, then use:
target=$(eval echo $(<path.txt))
for example:
$ target=$(eval echo $(<path.txt)); echo "$target"
/home/david/filedump/
This might not necessarily suit your needs (depending on the context of the code you provided), but the following worked for me:
targetfile="path.txt"
target=$(cat $targetfile)
echo $target
Here's a safer alternative than eval. In general, you should not be using configuration files that require bash to evaluate their contents; that just opens a security risk in your script. Instead, detect if there is something that requires evaluation, and handle it explicitly. For example,
IFS= read -r path < path.txt
if [[ $path =~ '$HOME' ]]; then
target=$HOME/${path#\$HOME}
# more generally, target=${path/\$HOME/$HOME}, but
# when does $HOME ever appear in the *middle* of a path?
else
target=$path
fi
This requires you to know ahead of time what variables might appear in path.txt, but that's a good thing. You should not be evaluating unknown code.
Note that you can use any placeholder instead of a variable in this case; %h/filedump can be detected and processed just as easily as $HOME/filedump, without the presumption that the contents can or should be evaluated as shell code.