I have multiple files with different job names. The job name is specified as follows.
#SBATCH --job-name=01_job1 #Set the job name
I want to use sed/awk/grep to automatically get the name, that is to say, what follows '--job-name=' and precedes the comment '#Set the job name'. For the example above, I want to get 01_job1. The job name could be longer for several files, and there are multiple = signs in following lines in the file.
I have tried using grep -oP "job-name=\s \K\w " file
and get an empty output. I suspect that this doesn't work because there is no space between 'name=' and '01_job1', so they must be understood as a single word.
I also unsuccessfully tried using awk '{for (I=1;I<NF;I ) if ($I == "name=") print $(I 1)}' file
, attempting to find the characters after 'name='.
Lastly, I also unsuccessfully tried sed -e 's/name=\(.*\)#Set/\1/'
file to find the characters between 'name=' and the beginning of the comment '#Set'. I receive the whole file as my output when I attempt this.
I appreciate any guidance. Thank you!!
CodePudding user response:
Use this, you was close, just correctness of your grep -oP
attempt (the main issue if you are trying to match a space
after =
character):
$ grep -oP -- '--job-name=\K\S ' file
01_job1
Explanations:
From man bash
--
A
--
signals the end of options and disables further option processing.
Any arguments after the--
are treated as filenames and arguments. An argument of-
is equivalent to--
That's because if the string you'd grep
start with a -
, grep
try to treat it as a switch
The regex matches as follows:
NODE EXPLANATION
----------------------------------------------------------------------
--job-name= '--job-name='
----------------------------------------------------------------------
\K restart the match look-around
----------------------------------------------------------------------
\S non-whitespace (all but \n, \r, \t, \f,
and " ") (1 or more times (matching the
most amount possible))
----------------------------------------------------------------------
CodePudding user response:
You need to match the whole string with sed and capture just what you need to get, and use -n
option with the p
flag:
sed -n 's/.*name=\([^[:space:]]*\).*/\1/p'
See the online demo:
#!/bin/bash
s='#SBATCH --job-name=01_job1 #Set the job name'
sed -n 's/.*name=\([^[:space:]]*\).*/\1/p' <<< "$s"
# => 01_job1
Details:
-n
- suppresses default line output.*
- any textname=
- a literalname=
string\([^[:space:]]*\)
- Group 1 (\1
): any zero or more chars other than whitespace.*
- any textp
- print the result of the successful substitution.
CodePudding user response:
Simlar to the answer of Gilles Quenot
grep -oP -- '--job-name=\K.*(?= *# *Set the job name)'
This adds a look-ahead to ensure that the string is followed by #Set the job name
CodePudding user response:
1st solution: In GNU awk
with your shown samples please try following awk
code.
awk -v RS=' --job-name=\\S ' 'RT && split(RT,arr,"="){print arr[2]}' Input_file
OR a non-one liner form of above GNU awk
code would be:
awk -v RS=' --job-name=\\S ' '
RT && split(RT,arr,"="){
print arr[2]
}
' Input_file
2nd solution: Using any awk
please try following code.
awk -F'[[:space:]] |--job-name=' '{print $3}' Input_file
3rd solution: Using GNU grep
please try following code with your shown samples and using non-greedy .*?
approach here in regex.
grep -oP '^.*?--job-name=\K\S ' Input_file
CodePudding user response:
You can use a lookbehind and lookahead with GNU grep to get exactly what you describe:
grep -oP '(?<=--job-name=)\S (?=\s #Set the job name)' file
Or with awk:
awk '/^#SBATCH[[:space:]] --job-name=/ &&
/#Set the job name$/ {
sub(/^[^=]*=/,"")
sub(/#[^#]*$/,"")
print
}' file
Or perl:
perl -lnE 'say $1 if /(?<=--job-name=)(\S )(?=\s #Set the job name)/' file
Any prints:
01_job1