storing output of echo in a variable - shell

I am using echo and sed to print a string between two strings, but it is giving me error "no such file of directory"
$SEARCH_1=12
$FO_FILE=myfile.txt
SEARCH=$(head -$SEARCH_1 $FO_FILE | tail -1 | grep BShare)
LOC=echo $SEARCH_2 | sed 's/\(.*\)BShare>\(.*\)<\/BShare\(.*\)/\2/g'
If I don't use LOC= and use only echo it prints the string correctly.
example
<test>mystring</test> will be printed as mystring
but if I assign the echo command to a variable it says "no such file or directory"

To capture the output of a command and assign it to a variable you need to use backticks or $( ... ), e.g.
LOC=`echo $SEARCH_2 | sed 's/\(.*\)BShare>\(.*\)<\/BShare\(.*\)/\2/g'`
or
LOC=$(echo $SEARCH_2 | sed 's/\(.*\)BShare>\(.*\)<\/BShare\(.*\)/\2/g')
The problem with the original command
LOC=echo $SEARCH_2 | sed 's/\(.*\)BShare>\(.*\)<\/BShare\(.*\)/\2/g'
is that the shell here tries to run what ever $SEARCH_2 evaluates to (with a environmental variable LOC set to value echo), and pipe the output of that to sed.

Related

How can I avoid Delimiters replacing Date values while printing in shell script?

For the command:
cat <file_name>.asc | head -1
Output:
10/30/2006,19:41:58,1.4871,1,E
I wanted to append commas to this line to maintain field consistency.
So I tried various combinations like issuing,
Command : echo cat <file_name>.asc | head -1,,,
Output : ,,,30/2006,19:41:58,1.4871,1,E
Command : echo cat <file_name>.asc | head -1,
Output : ,0/30/2006,19:41:58,1.4871,1,E
Command : echo cat <file_name>.asc | head -1",,,"
Output : ,,,30/2006,19:41:58,1.4871,1,E
Command : chk=$(echo cat <file_name>.asc | head -1)
echo ${chk},,,
Output : ,,,30/2006,19:41:58,1.4871,1,E
But my expected output is very simple,
10/30/2006,19:41:58,1.4871,1,E,,,
Actually my logic is to open a file with CAT and do a while operation on each line to check the data and append comma wherever needed and write the output to another file.
If I understood correctly, you want do this conversion:
10/30/2006,19:41:58,1.4871,1,E --> 10/30/2006,19:41:58,1.4871,1,E,,,
If so, then you should use sed util:
cat <file_name>.asc | sed -e 's/$/,,,/' > output_file
echo `head -n 1 cat.asc`,,,
If you need this in a variable, it goes like this:
X=`head -n 1 cat.asc`,,,
This answers the question which you asked. However, you also mention that you want to process a whole file and do some adjustment for each line. In this case, I don't see how this approach will help....

Remove last two path components of a path in a shell variable

I have a variable var=/usr/local/bin/test/exec
Now i have to remove last 2 path components in the above variable say:
var=/usr/local/bin/
After removing the last 2 strings I have to use this variable 'var' in a shell loop.
I tried:
var='/usr/local/bin/test/exec'
echo ${var#$(dirname "$(dirname "$s")")/}
Output:
test/exec
I am getting the truncated part as output, but I was expecting the rest of the part, not the truncated part.
You may be interested in the shell's internal substring processing operators: %, %%, # and##. Observe:
#!/bin/sh
var=/usr/local/bin/test/exec
# use shell substring processing to cut the variable down to size:
var="${var%/*}"
var="${var%/*}"
echo "$var"
# Manipulate the resulting string in a loop
for i in 1 2 3
do echo "${var}${i}"
done
OK after some googling i have found the solution for this:
var1="$(echo $var | cut -d '/' -f-4)"
If you don't know the field count, there is a standard awk solution. However, I'll show another trick using rev
var='/usr/local/bin/test/exec'; echo $var | rev | cut -d/ -f3- | rev
will give
/usr/local/bin
You can try this method also
var=/usr/local/bin/test/exec
sed 's_\(.*\)/.*/.*$_\1_' <<< $var
Another Method
sed 's_\(.*\)\(/.*\)\{2\}$_\1_' <<< $var
Output:
/usr/local/bin

How to use sed to extract a string [duplicate]

This question already has answers here:
BASH extract value after string in variable Not file [duplicate]
(2 answers)
Closed last year.
I need to extract a number from the output of a command: cmd. The output is type: 1000
So my question is how to execute the command, store its output in a variable and extract 1000 in a shell script. Also how do you store the extracted string in a variable?
This question has been answered in pieces here before, it would be something like this:
line=$(sed -n '2p' myfile)
echo "$line"
if [ `echo $line || grep 'type: 1000' ` ] then;
echo "It's there!";
fi;
Store output of sed into a variable
String contains in Bash
EDIT: sed is very limited, you would need to use bash, perl or awk for what you need.
This is a typical use case for grep:
output=$(cmd | grep -o '[0-9]\+')
You can write the output of a command or even a pipeline of commands into a shell variable using so called command substitution:
variable=$(cmd);
In comments it appeared that the output of cmd contains more lines than the type : 1000. In this case I would suggest sed:
output=$(cmd | sed -n 's/type : \([0-9]\+\)/\1/p;q')
You tagged your question as sed but your question description does not restrict other tools, so here's a solution using awk.
output = `cmd | awk -F':' '/type: [0-9]+/{print $2}'`
Alternatively, you can use the newer $( ) syntax. Some find the newer syntax preferable and it can be conveniently nested, without the need for escaping backtics.
output = $(cmd | awk -F':' '/type: [0-9]+/{print $2}')
If the output is rigidly restricted to "type: " followed by a number, you can just use cut.
var=$(echo 'type: 1000' | cut -f 2 -d ' ')
Obviously you'll have to pipe the output of your command to cut, I'm using echo as a demo.
In addition, I'd use grep and then cut if the string you are searching is more complex. If we assume there can be all kind of numbers in the text, but only one occurrence of "type: " followed by a number, you can use the command:
>> var=$(echo "hello 12 type: 1000 foo 1001" | grep -oE "type: [0-9]+" | cut -f 2 -d ' ')
>> echo $var
1000
You can use the | operator to send the output of one command to another, like so:
echo " 1\n 2\n 3\n" | grep "2"
This sends the string " 1\n 2\n 3\n" to the grep command, which will search for the line containing 2. It sound like you might want to do something like:
cmd | grep "type"
Here is a plain sed solution that uses a regualar expression to find the number in your string:
cmd | sed 's/^.*type: \([0-9]\+\)/\1/g'
^ means from the start
.* can be any character (also none)
\([0-9]\+\) are numbers (minimum one character)
\1 means it takes the first pattern it finds (and only in this case) and uses it as replacement for the whole string

How to concatenate stdin and a string?

How to I concatenate stdin to a string, like this?
echo "input" | COMMAND "string"
and get
inputstring
A bit hacky, but this might be the shortest way to do what you asked in the question (use a pipe to accept stdout from echo "input" as stdin to another process / command:
echo "input" | awk '{print $1"string"}'
Output:
inputstring
What task are you exactly trying to accomplish? More context can get you more direction on a better solution.
Update - responding to comment:
#NoamRoss
The more idiomatic way of doing what you want is then:
echo 'http://dx.doi.org/'"$(pbpaste)"
The $(...) syntax is called command substitution. In short, it executes the commands enclosed in a new subshell, and substitutes the its stdout output to where the $(...) was invoked in the parent shell. So you would get, in effect:
echo 'http://dx.doi.org/'"rsif.2012.0125"
use cat - to read from stdin, and put it in $() to throw away the trailing newline
echo input | COMMAND "$(cat -)string"
However why don't you drop the pipe and grab the output of the left side in a command substitution:
COMMAND "$(echo input)string"
I'm often using pipes, so this tends to be an easy way to prefix and suffix stdin:
echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix
There are some ways of accomplish this, i personally think the best is:
echo input | while read line; do echo $line string; done
Another can be by substituting "$" (end of line character) with "string" in a sed command:
echo input | sed "s/$/ string/g"
Why i prefer the former? Because it concatenates a string to stdin instantly, for example with the following command:
(echo input_one ;sleep 5; echo input_two ) | while read line; do echo $line string; done
you get immediatly the first output:
input_one string
and then after 5 seconds you get the other echo:
input_two string
On the other hand using "sed" first it performs all the content of the parenthesis and then it gives it to "sed", so the command
(echo input_one ;sleep 5; echo input_two ) | sed "s/$/ string/g"
will output both the lines
input_one string
input_two string
after 5 seconds.
This can be very useful in cases you are performing calls to functions which takes a long time to complete and want to be continuously updated about the output of the function.
You can do it with sed:
seq 5 | sed '$a\6'
seq 5 | sed '$ s/.*/\0 6/'
In your example:
echo input | sed 's/.*/\0string/'
I know this is a few years late, but you can accomplish this with the xargs -J option:
echo "input" | xargs -J "%" echo "%" "string"
And since it is xargs, you can do this on multiple lines of a file at once. If the file 'names' has three lines, like:
Adam
Bob
Charlie
You could do:
cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"
Also works:
seq -w 0 100 | xargs -I {} echo "string "{}
Will generate strings like:
string 000
string 001
string 002
string 003
string 004
...
The command you posted would take the string "input" use it as COMMAND's stdin stream, which would not produce the results you are looking for unless COMMAND first printed out the contents of its stdin and then printed out its command line arguments.
It seems like what you want to do is more close to command substitution.
http://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html#Command-Substitution
With command substitution you can have a commandline like this:
echo input `COMMAND "string"`
This will first evaluate COMMAND with "string" as input, and then expand the results of that commands execution onto a line, replacing what's between the ‘`’ characters.
cat will be my choice: ls | cat - <(echo new line)
With perl
echo "input" | perl -ne 'print "prefix $_"'
Output:
prefix input
A solution using sd (basically a modern sed; much easier to use IMO):
# replace '$' (end of string marker) with 'Ipsum'
# the `e` flag disables multi-line matching (treats all lines as one)
$ echo "Lorem" | sd --flags e '$' 'Ipsum'
Lorem
Ipsum#no new line here
You might observe that Ipsum appears on a new line, and the output is missing a \n. The reason is echo's output ends in a \n, and you didn't tell sd to add a new \n. sd is technically correct because it's doing exactly what you are asking it to do and nothing else.
However this may not be what you want, so instead you can do this:
# replace '\n$' (new line, immediately followed by end of string) by 'Ipsum\n'
# don't forget to re-add the `\n` that you removed (if you want it)
$ echo "Lorem" | sd --flags e '\n$' 'Ipsum\n'
LoremIpsum
If you have a multi-line string, but you want to append to the end of each individual line:
$ ls
foo bar baz
$ ls | sd '\n' '/file\n'
bar/file
baz/file
foo/file
I want to prepend my sql script with "set" statement before running it.
So I echo the "set" instruction, then pipe it to cat. Command cat takes two parameters : STDIN marked as "-" and my sql file, cat joins both of them to one output. Next I pass the result to mysql command to run it as a script.
echo "set #ZERO_PRODUCTS_DISPLAY='$ZERO_PRODUCTS_DISPLAY';" | cat - sql/test_parameter.sql | mysql
p.s. mysql login and password stored in .my.cnf file

Pipes inside of sed

Is there a way to send the back references of the SED s/// command to pipes? In order to get an entry from the text, change it, and then write it back. I found that a substitution inside of SED works:
$ echo 'Test ....' | sed 's/Test/'$( echo "<\0>" )'/'
<Test> ....
But the first pipe does not:
$ echo 'Test ....' | sed 's/Test/'$( echo "<\0>" | tr 's' 'x' )'/'
<Test> ....
What is the reason? Additionally, I can't understand why this works at all. I thought that $() substitution should be processed before sed (all the more as I broke the quotes).
And how can I insert one s/// command into another using sed? I use bash.
The tr command is operating on the text "<\0>", not on "<Test>". The back reference isn't expanded in sed until after the pipeline completes. Your second example is equivalent to
foo=$( echo "<\0>" | tr 's' 'x' )
echo 'Test ....' | sed 's/Test/'$foo'/'
It's a little easier to see here that tr has no way of seeing "Test" in its input.
You can achieve the effect you're after with GNU sed and the e flag:
echo 'Test ....' | sed 's/Test.*/echo "<\0>" | tr s x/e'
Output:
<Text ....>

Resources