Bash and variables substitution - bash

I use this to generate svn logs for a specific user:
svn log | sed -n '/bob/,/-----$/ p'
which works fine. Now I would like to use a parameter/variable for the user:
USER="bob"
svn log | sed -n '/$USER/,/-----$/ p'
but it just give an empty log. How do I pass a parameter to the above command?

The correct way to do this is to use double quotes so that the bash variable can be expanded:
USER="bob"
svn log | sed -n "/$USER/,/-----$/p"
Adding more single quotes to "insert" a bash variable (as per the accepted answer) is not best practice. HTH.

Use single quotes:
USER="bob"
svn log | sed -n '/'$USER'/,/-----$/ p'

try:
svn log | sed -n '/"$USER"/,/-----$/ p'

Related

gitlab ci bash script variable modification

In GitLab CI script I wanted to
Remove any character other then numbers and dot (.) and
remove all the text after 2nd dot [Ex 5.6.7.8 -> 5.6] if dot exists in text.
So for that I have tried to use sed , but it's not working in GitLab Script (working on bash shell locally)
export BRANCH_NAME={$CI_COMMIT_REF_NAME} | sed 's/\.[^.]*$//' | sed 's/[^0-9.]//g'
any idea what is missing here ?
If sed is not going to work here then any other option to achieve the same?
Edit :
As per #WiktorStribiżew
- echo "$CI_COMMIT_REF_NAME" | sed 's/.[^.]$//' | sed 's/[^0-9.]//g'
- export BRANCH_NAME=${CI_COMMIT_REF_NAME} | sed 's/.[^.]$//' | sed 's/[^0-9.]//g'
echo is working but export is not
Using sed
$ export BRANCH_NAME=$(echo "$CI_COMMIT_REF_NAME" |sed 's/[A-Za-z]*//g;s/\([0-9]*\.[0-9]*\)\.[^ ]*/\1/g')
First of all, to remove all text after and including second dot you need
sed 's/\([^.]*\.[^.]*\).*/\1/'
The sed 's/\.[^.]*$//' sed command removes the last dot and any text after it.
Next, you must have made a typo and you actually meant to write ${CI_COMMIT_REF_NAME} and not {$CI_COMMIT_REF_NAME}.
So, you might be better off with
export BRANCH_NAME=$(echo "$CI_COMMIT_REF_NAME" | sed 's/\([^.]*\.[^.]*\).*/\1/' | sed 's/[^0-9.]//g')

How to replace "\n" string with a new line in Unix Bash script

Cannot seem to find an answer to this one online...
I have a string variable (externally sourced) with new lines "\n" encoded as strings.
I want to replace those strings with actual new line carriage returns. The code below can achieve this...
echo $EXT_DESCR | sed 's/\\n/\n/g'
But when I try to store the result of this into it's own variable, it converts them back to strings
NEW_DESCR=`echo $EXT_DESCR | sed 's/\\n/\n/g'`
How can this be achieved, or what I'm I doing wrong?
Here's my code I've been testing to try get the right results
EXT_DESCR="This is a text\nWith a new line"
echo $EXT_DESCR | sed 's/\\n/\n/g'
NEW_DESCR=`echo $EXT_DESCR | sed 's/\\n/\n/g'`
echo ""
echo "$NEW_DESCR"
No need for sed, using parameter expansion:
$ foo='1\n2\n3'; echo "${foo//'\n'/$'\n'}"
1
2
3
With bash 4.4 or newer, you can use the E operator in ${parameter#operator}:
$ foo='1\n2\n3'; echo "${foo#E}"
1
2
3
Other answers contain alternative solutions. (I especially like the parameter expansion one.)
Here's what's wrong with your attempt:
In
echo $EXT_DESCR | sed 's/\\n/\n/g'
the sed command is in single quotes, so sed gets s/\\n/\n/g as is.
In
NEW_DESCR=`echo $EXT_DESCR | sed 's/\\n/\n/g'`
the whole command is in backticks, so a round of backslash processing is applied. That leads to sed getting the code s/\n/\n/g, which does nothing.
A possible fix for this code:
NEW_DESCR=`echo $EXT_DESCR | sed 's/\\\\n/\\n/g'`
By doubling up the backslashes, we end up with the right command in sed.
Or (easier):
NEW_DESCR=$(echo $EXT_DESCR | sed 's/\\n/\n/g')
Instead of backticks use $( ), which has less esoteric escaping rules.
Note: Don't use ALL_UPPERCASE for your shell variables. UPPERCASE is (informally) reserved for system variables such as HOME and special built-in variables such as IFS or RANDOM.
Depending on what exactly you need it for:
echo -e $EXT_DESCR
might be all you need.
From echo man page:
-e
enable interpretation of backslash escapes
This printf would do the job by interpreting all escaped constructs:
printf -v NEW_DESCR "%b" "$EXT_DESCR"
-v option will store output in a variable so no need to use command substitution here.
Problem with your approach is use of old back-ticks. You could do:
NEW_DESCR=$(echo "$EXT_DESCR" | sed 's/\\n/\n/g')
Assuming you're using gnu sed as BSD sed won't work with this approach.

Extract range of lines using sed

I have defined two variables as follows:
var1=$(unzip -c ./*.zip | grep -n "Channel8"| cut -f1 -d":")
var2=$(unzip -c ./*.zip | grep -n "Channel10"| cut -f1 -d":")
I have a very big file and I would like to extract the range of lines between $var1 and $var2 using sed. I am trying the following
sed -n '/"$var1","$var"2p' $(unzip -c ./*.zip)
But with no success. Could you give an explanation why and how to fix it? Thanks.
You can use:
unzip -c ./*.zip | sed -n "$var1,$var2 p"
Fixes are:
Not using single quotes around shell variable
Removal of leading / from sed command
Use of pipeline instead of command substitution
Variables aren't expanded inside single quotes. Also, you need to pipe the output of unzip to sed, not use it as command-line arguments.
unzip -c ./*.zip | sed -n "${var1},${var2}p"
But it seems like you're doing this the hard way, reading the zip file 3 times. Just use the pattern you want to match as the range:
unzip -c ./*.zip | sed -n '/^extracting:.*Channel8/,/^extracting:.*Channel10/p'
Use double quotes to expand the vars:
sed -n "${var1},${var2}p" $(unzip -c ./*.zip)

Using Sed with regular expression to save results into a variable

What I'm trying to do is take user input as a string and parse a section of the string. The results from my regex I want to save into a new variable. Here is what I have so far.
#!/bin/bash
downloadUrl="$1"
pythonFile=echo $downloadUrl | sed '/Python-[\d+.]+tgz/'
echo "$downloadUrl"
echo "$pythonFile"
And here is my result.
sed: 1: "/Python-[\d+.]+tgz/": command expected
You forgot to run the commands in $() to get command substitution. Use:
pythonFile=$(echo $downloadUrl | sed '/Python-[\d+.]+tgz/')
See the manual for more details.
sed '/Python-[\d+.]+tgz/' is incorrect since you need to have a sed command like p and anyway it is only searching not really extracting part of input text.
You can use grep -oP
pythonFile$(grep -oP '/Python-[\d+.]+tgz/' <<< "$downloadUrl")
Or without -P
pythonFile$(grep -o '/Python-[0-9+.]\+tgz/' <<< "$downloadUrl")

How to get all revisions in subversion URL (trunk/branch) based on a string in svn comments?

Need some help on shell command to get all revs in subversion trunk URL based on a string in svn comments.
I figured out to get it on one file but not on URL.
I tried svn log URL --stop-on-copy and svn log URL --xml to get the revs but unsuccessful.
Thanks !!
Another way using sed. It's probably not perfect but it also works with multiline comments. Replace SEARCH_STRING for your personal search.
svn log -l100 | sed -n '/^r/{h;d};/SEARCH_STRING/{g;s/^r\([[:digit:]]*\).*/\1/p}'
For Subversion 1.8 it's
svn log URL --search STRING
Try following.
x="refactoring"; svn log --limit 10 | egrep -i --color=none "($x|^r[0-9]+ \|.*lines$)" | egrep -B 1 -i --color=none $x | egrep --color=none "^r[0-9]+ \|.*lines$" | awk '{print $1}' | sed 's/^r//g'
Replace refactoring with search string.
Change svn log parameters to suite your need.
Case insensitive matching is used (egrep -i).
Edit based on comment.
x="ILIES-113493"; svn log | egrep -i --color=none "($x|^r[0-9]+ \|.*lines$)" | egrep -B 1 -i --color=none $x | egrep --color=none "^r[0-9]+ \|.*lines$" | awk '{print $1}' | sed 's/^r//g'
Notes:
x is the variable to contain the search string, and x is used in
two places in the command.
In order to use x as a variable in the shell itself, you need to put entire command on a single line (from x=".."; svn log ... sed '...'). Semicolon ; can be used to separate multiple commands on the same line.
I had used --limit 10 in example to limit the number of log entries,
change that as well as use other svn log parameters to suite your
need. Using --limit 10 will restrict the search to 10 most recent log entries.
Thanks all for the help !! This worked for me:
svn log $URL --stop-on-copy | grep -B 2 $STRING | grep "^r" | cut -d"r" -f2 | cut -d" " -f1
Use "--stop-on-copy" or "--limit" options depending on the requirement.

Resources