How to find string from txt file and store in variable in BASH - bash

Requirement is to find a string from txt file and store it to variable.
file look like this(rsa.txt)
Encrypting String
... Input string : Test_123
... Encrypted string : $ENC(JEVOQyhZbVpkQmM0L3ArT2c4M05TZks5TmxRPT1+KQ==)
Required output (variable name : encstring):
encstring = $ENC(JEVOQyhZbVpkQmM0L3ArT2c4M05TZks5TmxRPT1+KQ==)
I tried below code but showing no result
encstring=$(grep -oE '$ENC[^()]*==)' <<< rsa.txt)

With awk, could you please try following. Simply, search for string /Encrypted string along with a condition to check if last field of that line has $ENC in it then last field for that line by using $NF.
encstring=$(awk '/Encrypted string/ && $NF~/\$ENC/{print $NF}'

You can use
encstring=$(sed -n 's/.*\(\$ENC(.*)\).*/\1/p' rsa.txt)
# OR
encstring=$(grep -oP '\$ENC\(.*?\)' rsa.txt)
See an online demo:
s='Encrypting String
... Input string : Test_123
... Encrypted string : $ENC(JEVOQyhZbVpkQmM0L3ArT2c4M05TZks5TmxRPT1+KQ==)'
encstring=$(sed -n 's/.*\(\$ENC(.*)\).*/\1/p' <<< "$s")
echo "$encstring"
# => $ENC(JEVOQyhZbVpkQmM0L3ArT2c4M05TZks5TmxRPT1+KQ==)
The sed -n 's/.*\(\$ENC(.*)\).*/\1/p' command does the following:
-n suppresses the default line output
s/.*\(\$ENC(.*)\).*/\1/ - finds any text, then captures $ENC(...) into Group 1 and then matches the rest of the string, and replaces the match with the Group 1 value
p - prints the result of the substitution.
The grep -oP '\$ENC\(.*?\)' command extracts all $ENC(...) matches, with any chars, as few as possible, between ( and ).

You are searching for ENC which is followed by 0 or more occurances of something which is not an open or closed parenthesis. However, in your input file, there is an open parenthese after ENC. Therefore [^()]* matches the null string. After this you expect the string ==). This would match only for the input ENC==)`.

You need to escape $ as \$ as it means "end of string" with -E

Related

sed replace string with pipe and stars

I have the following string:
|**barak**.version|2001.0132012031539|
in file text.txt.
I would like to replace it with the following:
|**barak**.version|2001.01.2012031541|
So I run:
sed -i "s/\|\*\*$module\*\*.version\|2001.0132012031539/|**$module**.version|$version/" text.txt
but the result is a duplicate instead of replacing:
|**barak**.version|2001.01.2012031541|**barak**.version|2001.0132012031539|
What am I doing wrong?
Here is the value for module and version:
$ echo $module
barak
$ echo $version
2001.01.2012031541
Assumptions:
lines of interest start and end with a pipe (|) and have one more pipe somewhere in the middle of the data
search is based solely on the value of ${module} existing between the 1st/2nd pipes in the data
we don't know what else may be between the 1st/2nd pipes
the version number is the only thing between the 2nd/3rd pipes
we don't know the version number that we'll be replacing
Sample data:
$ module='barak'
$ version='2001.01.2012031541'
$ cat text.txt
**barak**.version|2001.0132012031539| <<<=== leave this one alone
|**apple**.version|2001.0132012031539|
|**barak**.version|2001.0132012031539| <<<=== replace this one
|**chuck**.version|2001.0132012031539|
|**barak**.peanuts|2001.0132012031539| <<<=== replace this one
One sed solution with -Extended regex support enabled and making use of a capture group:
$ sed -E "s/^(\|[^|]*${module}[^|]*).*/\1|${version}|/" text.txt
Where:
\| - first occurrence (escaped pipe) tells sed we're dealing with a literal pipe; follow-on pipes will be treated as literal strings
^(\|[^|]*${module}[^|]*) - first capture group that starts at the beginning of the line, starts with a pipe, then some number of non-pipe characters, then the search pattern (${module}), then more non-pipe characters (continues up to next pipe character)
.* - matches rest of the line (which we're going to discard)
\1|${version}| - replace line with our first capture group, then a pipe, then the new replacement value (${version}), then the final pipe
The above generates:
**barak**.version|2001.0132012031539|
|**apple**.version|2001.0132012031539|
|**barak**.version|2001.01.2012031541| <<<=== replaced
|**chuck**.version|2001.0132012031539|
|**barak**.peanuts|2001.01.2012031541| <<<=== replaced
An awk alternative using GNU awk:
awk -v mod="$module" -v vers="$version" -F \| '{ OFS=FS;split($2,map,".");inmod=substr(map[1],3,length(map[1])-4);if (inmod==mod) { $3=vers } }1' file
Pass two variables mod and vers to awk using $module and $version. Set the field delimiter to |. Split the second field into array map using the split function and using . as the delimiter. Then strip the leading and ending "**" from the first index of the array to expose the module name as inmod using the substr function. Compare this to the mod variable and if there is a match, change the 3rd delimited field to the variable vers. Print the lines with short hand 1
Pipe is only special when you're using extended regular expressions: sed -E
There's no reason why you need extended here, stick with basic regex:
sed "
# for lines matching module.version
/|\*\*$module\*\*.version|/ {
# replace the version
s/|2001.0132012031539|/|$version|/
}
" text.txt
or as an unreadable one-liner
sed "/|\*\*$module\*\*.version|/ s/|2001.0132012031539|/|$version|/" text.txt

extract substring until first digit

I have the following string:
test1234a or test1234 for example and I want to extract only test from that string.
I tried the follwing
echo "Test12h" | sed -e 's/[0-9]\*$//' but is not working.
Is there any possibility to extract the substring until first digit?
Please let me know what I miss.
Thank you
The proper tool for extracting substrings matching a regexp from a command's output is grep. Like,
echo "Test12h" | grep -o '^[^[:digit:]]*'
will output Test.
If Test12h is in a variable, you don't even need external utilities; parameter expansions can easily handle that, e.g:
var='Test12h'
echo "${var%%[[:digit:]]*}"
Could you please try following.
sed 's/\([^0-9]*\).*/\1/' Input_file
OR
sed 's/[0-9][0-9a-zA-Z]*//' Input_file
If the source happens to reside in a variable you can use parameter substitution, eg:
$ for test in test1234a test1234 Test12h
do
echo "${test} => ${test//[0-9]*/}"
done
test1234a => test
test1234 => test
Test12h => Test
Where the general format is: ${var//Pattern/Replacement}; in the above:
var == test
Pattern == [0-9]* (first occurrence of a digit and then everything that follows
Replacement == '' (nothing, empty string)
So we end up stripping off everything after the first occurrence of a number.
You made a small error in your try:
echo "Test12h" | sed -e 's/[0-9].*$//' # will output Test
The \* expects a real * in the input:
echo "Test1*" | sed -e 's/[0-9]\*$//' # will output Test
The .* matches any number of any characters.

search a string from file which contains only specific symbol and number in unix through Grep command

I want to search a line from file which contains "+", number and character. If any other character available in string then complete string should be discarded.
A1264
13255
1255+*
*6_54
54789+
Output should be
A1264
13255
54789+
Record number 3 and 4 should not come as it contains some other character also.
You can try something like:
grep -E '^[a-zA-Z0-9\+]+$'
This will accept only a to z chars (small and caps), digits and + sign
If you have other symbols you can edit the command line:
# grep -E '^[a-fA-F0-9©]+$' a1
A1264
13255
54789©

Copy text from one line and create a new line with that next under it

I have a text file in which I want to find all of ID:= "abc123" when it finds that I want it to take that value of abc123 and create a new line and have a set string, newId:= "abc123 How can I do this within terminal?
I'd like to use bash, below are some examples, find the string '"ID": ", copy the value (abc123) and make a new line with this data.
"ID": "abc123"
"newID": "abc123"
You can do this:
sed -e 's/^"ID": "\(.*\)"/&\
"newID": "\1"/' myfile.txt
First, I'll try to explain the regular expression that searches for matches:
^ Matches the start of the line
"ID": " Matches that exact string
\(.*\) Matches a sequence of zero or more (*) of any character (.). Placing this expression between backslashed parenthesis creates a "capture", which allows us to store the resulting part of the match into an auxiliary variable \1.
" Matches the double-quote character
When it finds a match, it replaces it with:
& the match itself. This operator is an auxiliary variable that represents what was matched.
\<new-line> the backslash followed by an actual new line character escapes a new line, ie. it allows us to print a new line character into the replacement
"newId": " prints that exact string
\1 prints the contents of our capture, so it prints the ID we found
" prints a double quote character.
Hope this helps =)
Try doing this :
sed -r 's#^"ID": "([a-Z0-9]+)"#"newID": "\1"#' file.txt
sed : the executable
-r : extented mode (no need to backslash parenthesis)
s : we perform a substitution, skeleton is s#origin#replacement# (the separator can be anything)
^ : means start of line in regex
( ) : parenthesis is a capture
"newID": is the start of the new string
\1 : is the end of the substituted string (the captured string)
Considering your question is very vague I made some assumptions which will become apparent in my implementation.
INPUT FILE -- call it t
ID="one"
dkkd
ID="two"
ffkjf
ID="three"
ldl
Command ran on input file
for line in `cat t`; do newID=`echo $line | grep ID | cut -d= -f2`; if [[ "$newID" != "" ]]; then echo $line >> t2; echo newID=$newID >> t2; else echo $line >> t2; fi; done
OUTPUT FILE -- Name is t2 (apparent from the command)
ID="one"
newID="one"
dkkd
ID="two"
newID="two"
ffkjf
ID="three"
newID="three"
ldl
Basically this command goes line by line in the file (in this case called t) looks for an ID line. If it finds one it gets its value, prints the original line with the ID and then prints another one with a newID following right after. If the line in question does not have and ID then it just prints the line it self.
Things to note:
If you have any other line in the file that contains "ID" in it but is not the normal ID that you requested, this will not work.

String manipulation required

Here is a sample string . I would like to get the output from this in the specified format.
String:
/vob/TEST/.##/main/ch_vobsweb/1/VOBSWeb/main/ch_vobsweb/4/VobsWebUI/main/ch_vobsweb/2/VaultWeb/main/ch_vobsweb/2/func.js
filename;path to file
func.js;VOBSWeb/VosWebUI/VaultWeb/func.js
The filename is listed at the end of the whole string , and it's path is supposed to be stripped using the characters after each numeric value (eg. /1/VOBSWeb/ and then /4/VobsWebUI and then /2/vaultWeb)
one way
$ string="/vob/TEST/.##/main/ch_vobsweb/1/VOBSWeb/main/ch_vobsweb/4/VobsWebUI/main/ch_vobsweb/2/VaultWeb/main/ch_vobsweb/2/func.js"
$ path=$(echo "$string" | sed "s|\/[0-9]\/|\n|g"|sed 's|\/.*||' | tr "\n" "/"|sed 's/\/$//')
$ echo ${path##*/}
func.js
$ echo ${path%\/*}
/VOBSWeb/VobsWebUI/VaultWeb

Resources