This question already has answers here:
Is it possible to insert arguments at different points in a command in linux while piping
(2 answers)
Closed 9 days ago.
I need to pass two arguments to the same command. The output of the first command look like this:
BLA BLE
A1 B2
A2 B3
Right now I using this for using the first argument
firstCommand | tail -n1 | awk '{print $1}' | xargs -I_ secondCommand _
But the secondCommand has changed and right now I need to pass a second argument
secondComman A --second B
Is this posssible using xargs?
I try multiple stackoverflow solution, but none with was succesful.
Add printing 2nd argument to awk and capture 2 arguments with xargs:
firstCommand | tail -n1 | awk '{print $1,$2}' | xargs -n2 sh -c 'secondCommand "$1" --second "$2"' _
Related
This question already has answers here:
How to grep for contents after pattern?
(8 answers)
Closed last month.
How to extract the IP address of the output of the gcloud command mentioned bellow?
The goal is to extract the IP_ADRESS where TARGET contains targetPools and store it in a variable.
$ gcloud compute forwarding-rules list
>output:
NAME: abc
REGION: us
IP_ADDRESS: 00.000.000.000
IP_PROTOCOL: abc
TARGET: us/backendServices/abc
NAME: efg
REGION: us
IP_ADDRESS: 11.111.111.111
IP_PROTOCOL: efg
TARGET: us/targetPools/efg
desired output:
IP="11.111.111.111"
my attempt:
IP=$(gcloud compute forwarding-rules list | grep "IP_ADDRESS")
it doesn't work bc it need to
get the one with TARGET contains targetPools
extract the IP_ADRESS
store in local variable to be used
But not sure how to do this, any hints?
Using awk:
gcloud ... 2>&1 | awk -F: 'BEGIN {RS=""} $10 ~ /targetPools/ {print $6}'
With your given input, you could chain a few commands with pipes. That means there is always one line of text/string in between TARGET and IP_ADDRESS.
gcloud ... 2>&1 | grep -FB2 'TARGET: us/targetPools/efg' | head -n1 | sed 's/^.*: *//'
You could do without the head, something like
gcloud ... 2>&1 | grep -FB2 'TARGET: us/targetPools/efg' | sed 's/^.*: *//;q'
Some code explanation.
2>&1 Is a form of shell redirection, it is there to capturestderr and stdout.
-FB2 is a shorthand for -F -B 2
See grep --help | grep -- -B
See grep --help | grep -- -F
sed 's/^.*: *//'
^ Is what they call an anchor, it means from the start.
.* Means zero or more character/string.
. Will match a single string/character
* Is what they call a quantifier, will match zero or more character string
: Is a literal : in this context
* Will match a space, (zero or more)
// Remove what ever is/was matched by the pattern.
q means quit, without it sed will print/output all the lines that was matched by grep
This question already has answers here:
How do I set a variable to the output of a command in Bash?
(15 answers)
Closed 3 years ago.
I'm looking to store the hash of my most recently downloaded file in my downloads folder as a variable.
So far, this is what I have:
md5sum $(ls -t | head -n1) | awk '{print $1}'
Output:
user#ci-lux-soryan:~/Downloads$ md5sum $(ls -t | head -n1) | awk '{print $1}'
c1924742187128cc9cb2ec04ecbd1ca6
I have tried storing it as a variable like so, but it doesn't work:
VTHash=$(md5sum $(ls -t | head -n1) | awk '{print $1}')
Any ideas, where am I going wrong
As #Cyrus outlined parsing ls has its own pitfalls and therefore better to avoid it altogether rather than allowing unexpected corner cases. The following shall facilitate the requirements epitomised.
VTHash="$(find -type f -mtime 0 | tail -n 1 | xargs md5sum | awk '{ print $1 }')"
This question already has answers here:
How to process each output line in a loop?
(7 answers)
Closed 4 years ago.
Reading how to get substring in bash, I found out the following commands works:
var="/aaa/bbb/ccc/ddd"
echo ${var##*/}
Which produces "ddd"
My complete problem is to make this dinamically reading from a pipe:
I want to achieve something like this:
echo /aaa/bbb/ccc/ddd | xargs echo ${MyVar##*/}
But it is not working.
I tried to use -I option follwing way:
echo /aaa/bbb/ccc/ddd | xargs -I MyVar echo ${MyVar##*/}
And did not work either, (I think it does not interpolate it)
Any way to solve this?
Is it posible to achieve also to read substring left part, instead of right part?
You may use it like this:
echo '/aaa/bbb/ccc/ddd' | xargs -I {} bash -c 'echo "${1##*/}"' - {}
ddd
or just use awk:
echo '/aaa/bbb/ccc/ddd' | awk -F/ '{print $NF}'
You can do this :
echo '/aaa/bbb/ccc/ddd' | sed -E 's/(.*\/)(.*)/\2/g' | xargs -n 1 $1
Hope it helps!
I am trying to execute the one liner below as a part of bash script.
command1 |grep -ID|grep -v + | awk '{print "command2" $2}'|bash
The first part of the pipe prints the info below:
root#system:~# command1 |grep -v ID|grep -v +
| id | name | mac_address | fixed_ips |
| 00277225-34fa-48f5-9a2a-ee5f1c5b1dcb | dummy | fa:18:3e:c4:85:94 | {"subnet_id": "0cd4d824-4420-4049-87c3-ed33c3addbf5", "ip_address": "11.170.1.121"} |
:
:
| ff9a6ed5-9694-45bc-bf71-59565f96d809 | BAT-T0-A2-0-7-tport | fa:18:3e:62:70:fb | {"subnet_id": "f9ae81ed-3b1a-45a7-96fd-c417ed32
So, $2 in awk command2 is "00277225-34fa-48f5-9a2a-ee5f1c5b1dcb".
e.g.
command2 00277225-34fa-48f5-9a2a-ee5f1c5b1dcb
The whole purpose of this one-liner is to execute a number of "command2" instances with different parameter values from the printout above.
e.g.
command2 00277225-34fa-48f5-9a2a-ee5f1c5b1dcb
command2 ff9a6ed5-9694-45bc-bf71-59565f96d809
:
:
But I can not make the $2 recognized the way below
command1 |grep -ID|grep -v + | awk '{print "command2" $2}'|bash
I think I am missing few syntax tricks here (as newbie).
p.s: If I copy / paste the whole line in command line, it works fine.
You seem to be looking for
command1 | awk '!/ID/ && !/\+/ {print $2}' | xargs -n 1 command2
I refactored the ugly useless greps into the Awk script; but the real beef here is xargs. It reads parameters from standard input and passes them on to the command you supply in the positional parameters.
The option -n 1 says to only accept one additional argument at a time; but if command2 is a well-written standard Unix command, it can probably accept an arbitrary number of arguments, and will simply loop over them. In that case, removing -n 1 will be a lot more efficient.
Incidentally, your original attempt was fairly close; you should have added a space after command2 in the print statement. But I hope this solution will also help you see how to "think Unix".
This question already has answers here:
How to pass command output as multiple arguments to another command
(5 answers)
Closed 3 years ago.
I have this two step bash command:
L=`wc -l testfile | cut -d' ' -f1`
myprogram testfile $L testfile.out
Long story short, myprogram needs the line count as an input.
I want to combine this into one line.
This does not work because using redirect | to - passes stdout stream as a file, not a string.
wc -l testfile | cut -d' ' -f1 | myprogram testfile - testfile.out
Is there a way to combine this into one line?
Use process substitution:
myprogram testfile $(wc -l < testfile) testfile.out
^^^^^^^^^^^^^^^^^^^
This way, wc -l < testfile is evaluated together with the call of the program and you have both commands combined.
Note wc -l < file returns you just the number, so you don't have to do cut or any other thing to clean the output.