I'm writing a code in groovy to read a file line by line and perform an action (for ex: build a code for a specific configuration) based on the information available in the line.
The following groovy code runs fine for me, except that i want to ignore or skip the first line or rather any line which starts with # or comment (//).
__SAMPLE_GROOVY_CODE__
input_file = '/home/user/inputFile.txt'
// read all the lines into a list, each line is an element in the list
File FH1 = new File(input_file)
def lines = FH1.readLines()
for (line in lines)
{
env.c_num = sh(returnStdout: true, script: "echo '${line}' | cut -d ':' -f 1").trim();
env.p_num = sh(returnStdout: true, script: "echo '${line}' | cut -d ':' -f 2").trim();
env.p_len = p_num.length();
println("INFO: Length is ${p_len} \n");
if(env.p_len != '0')
{
println ("INFO: Build is required !! \n");
println ("INFO: c_num is: ${c_num} \n");
println ("INFO: p_num is: ${p_num} \n");
// Code for build will come here..!!
}
else
{
println("INFO: Build is NOT required !! \n");
}
}
__INPUT_FILE__
$> cat /home/user/inputFile.txt
# Details of inputFile.txt
1234-A0: aa ab ac ad ae al
5678-B0:
2345-B0: ba
3456-B0:
4567-B0: ca
Related
I have the following defined in my multibranch declarative pipeline:
steps {
script {
BUILD_PROD_FLAG = sh(returnStdout: true, script: "[ ${BUILD_PROD} = true ] && echo TRUE || echo FALSE; ").trim()
BUILD_PROD_FLAG_SECOND = expression { if (params.BUILD_PROD) { return "TRUE" } else { return "FALSE" } }
}
sh "echo alternative way to get true/false set (want this to say FALSE): ${BUILD_FLAG_SECOND}"
}
The first variable BUILD_PROD_FLAG works fine.
I would like to eliminate the convoluted bash spawning employed there.
The second one does not work:
Multibranch_PR-1#tmp/durable-212f3652/script.sh: 1: /home/ubuntu/workspace/s_InsightCamera_Multibranch_PR-1#tmp/durable-212f3652/script.sh: Syntax error: "(" unexpected
This apparently is due to
Which I am not able to comprehend.
When the expression block is removed it fails to parse:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 67: unexpected token: if # line 67, column 57.
BUILD_FLAG_SECOND = if (params
^
1 error
And when I tried something else that is different:
BUILD_FLAG_SECOND = expression { return params.BUILD_PROD ? "TRUE" : "FALSE" }
I get the same Syntax error: "(" unexpected error. I don't understand why this is a .sh shell script, by the way.
Update: OK I think I get why it's a .sh, that's just the sh clause near the bottom that I have.
I also thought I solved it because I did neglect to quote things for the shell, but with the adjustment:
sh "echo 'alternative way to get true/false set (want this to say FALSE):' ${BUILD_FLAG_SECOND}"
Still the same error:
I think it is for real trying to interpolate the string #expression(<anonymous>=org.jenkinsci.plugins.workflow.cps.CpsClosure2#4a286654) in place of the BUILD_FLAG_SECOND variable...
Are you ready for the epic facepalm that is the solution?
BUILD_FLAG_SECOND = params.BUILD_PROD ? "TRUE" : "FALSE"
That's it.
I have a Jenkins pipeline script and it has to read the contents from a properties one by one which is having as a key-value pair. I need to split key and value separately. Below are the properties and groovy file which I am using.
To be read file (mypropsfile.properties) :
product1=workspacename1:path1/path2/path3
product2=workspacename2:path1/path2/path3
product3=workspacename3:path1/path2/path3
My groovy file:
stage('readfromfile') {
steps {
script{
def readpropscontent = readProperties file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
for (String item : readpropscontent) {
echo "item ::: "+item
def readpropscontentfile2 = item.split("=")[0];
echo 'readpropscontentfile2 ::: '+readpropscontentfile2
}
}
}
}
Updated groovy file to split the value:
def readpropscontent = readFile file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
for (String item : readpropscontent.split('\n')) {
echo "item ::: "+item
def PropsFileValue = item.split("=")[1];
echo 'PropsFileValue ::: '+PropsFileValue
for (String splittingparams : PropsFileValue) {
def path1= splittingparams.split(":")[0];
echo 'path1::: '+path1
//def path2= splittingparams.split(":")[1];
//def path3= splittingparams.split("/")[1];
}
when I try to run it in Jenkins pipeline, I face the below issue:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.util.AbstractMap$SimpleImmutableEntry.split() is applicable for argument types: (java.lang.String) values: [=]
Possible solutions: split(groovy.lang.Closure), wait(), wait(long), sprintf(java.lang.String, [Ljava.lang.Object;), getAt(java.lang.String), print(java.io.PrintWriter)
I don't want to hardcode the key to fetch its value, by reading the file line by line I need to get the key and value. Can someone provide the inputs to resolve this? Thank you !
The readProperties method returns a Map of properties. So you don't have to iterate to read them, simply use the key(name of the property) to extract the value for a specific property.
stage('readfromfile') {
steps {
script{
def readpropscontent = readProperties file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
echo "PROP1 :::: ${readpropscontent['product1']}"
echo "PROP2 :::: ${readpropscontent['product2']}"
echo "PROP3 :::: ${readpropscontent['product3']}"
}
}
}
Update 1
Printing all keys and values from properties.
stage('readfromfile') {
steps {
script{
def readpropscontent = readProperties file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
readpropscontent.each{ k,v ->
echo "KEY = $k :::: VAL = $v "
}
}
}
}
Update 2
Using readFile instead of readProperties
steps {
script{
def readpropscontent = readFile file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
for (String item : readpropscontent.split('\n')) {
echo "item ::: "+item
def readpropscontentfile2 = item.split("=")[0];
echo 'readpropscontentfile2 ::: '+readpropscontentfile2
}
}
}
My usual way to submit a file is:
p4 submit –d “some description” filename
I could do:
p4 submit
and use the editor, but I always have many files open, so that method is inconvenient
Several times, I have mistakenly typed
p4 submit –d "some description"
(forgot the filename)
This submitted dozens of open files to production, with unintended consequences.
Time to panic and spend the afternoon doing damage control.
I would like to prevent p4 -d when the filename is not specified.
If you are using Linux you can define function in your .bashrs file that validates number of arguments and won't let you submit if you miss4th parameter.
function p4()
{
# validate what parameters are passed and if they are correct
# pass them to /opt/perforce/p4 ...
}
Thanks #pitseeker
I created a Perl wrapper "p4s" which checks the arguments and forwards the call to the real "p4 submit".
#!/usr/bin/perl
use warnings;
use strict;
use Capture::Tiny 'capture_merged';
die "Description and file is required!\n" if #ARGV < 2;
my ($description, #files) = #ARGV;
if ( -f $description ) {
die "It looks like you forgot the description before the filenames";
}
my $cmd;
my %summary;
print `date`;
for my $file (#files) {
if ( ! -f $file ) {
$summary{$file} = "File $file not found!";
next;
}
my $pwd = `pwd`;
chomp $pwd;
# print p4 filelog to screen
print `ls -l $file`;
$cmd = "p4 filelog $file | head -n 2";
$cmd = "p4 fstat -T 'headRev' $file";
print $cmd . "\n";
my $filelog = `$cmd`;
print "$filelog" . "\n";
$cmd = "p4 diff -sa $file";
my ($merged, $status) = Capture::Tiny::capture_merged {system($cmd)};
if ( ! $merged ) {
$summary{$file} = "Skipped since the local file does not differ from p4";
next;
}
# p4 submit
$cmd = "p4 submit -r -d \"$description\" $file";
print $cmd . "\n";
($merged, $status) = Capture::Tiny::capture_merged {system($cmd)};
chomp $merged;
print $merged . "\n";
if ( $merged =~ /No files to submit from the default changelist/ ) {
$summary{$file} = "$merged (You may need to 'p4 add' or 'p4 edit' this file)";
next;
}
$summary{$file} = "Success";
}
if ( scalar #files > 0 ) {
print "\nSummary:\n";
for my $file (#files) {
printf "%s %s\n", $file, $summary{$file};
}
}
Sorry for confusing you,
well, actually i want to send serial message to my arduino which is connected to /dev/ttyACM0 and it can be done by typing this command into terminal
$ echo "Hello Arduino" > /dev/ttyACM0
so, i need my awk to send a command just like that.
Here is my PBH.awk file:
BEGIN{
FS = "[ .]";
RS = "\0";
IGNORECASE = 1;
}{
for (i=1;i<NF;i++){
if(i == 1){
printf("Diketahui : %s\n",$18);}
if($i=="y" && $(i+1)=="=")
{
printf(" Persamaan : %s %s %s %s %s %s %s %s %s %s %s\n",$(i),$(i+1),$(i+2),$(i+3),$(i+4),$(i+5),$(i+6),$(i+7),$(i+8),$(i+9),$(i+10))
inisialisasi = "stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts"
kirim = "echo \"Field2 contains: $2""\" > /dev/ttyACM0"
print | inisialisasi
print | kirim
}
}
}
and here is the soalPBH.txt:
Persamaan gelombang berjalan pada seutas tali dinyatakan dengan y = 0,02 sin (20 π t – 0,2 π x). Jika x dan y dalam cm dan t dalam sekon, tentukan:
Then i run my awk with
$ awk -f PBH.awk soalPBH.txt
My program doesnt send the text on field number 2.
Is there something wrong with this??
kirim = "echo \"Field2 contains: $2""\" > /dev/ttyACM0"
Its VERY unclear what you're trying to do. Is this it:
$ cat file
field1 field2 field3
$ awk '{printf "echo \"Hello Arduino %s\" > /dev/ttyACM0\n", $2}' file
echo "Hello Arduino field2" > /dev/ttyACM0
If not, clarify your question and provide some clear sample input and expected output.
Given your updated question, just move the quote so $2 is outside of the quotes instead of inside of them, i.e. "$2 instead of $2":
kirim = "echo \"Field2 contains: " $2 "\" > /dev/ttyACM0"
Then tell us if you still have a problem.
I am trying to extract 4th column from csv file (comma separated, and skipping first 2 header lines) using this command,
awk 'NR <2 {next}{FS =","}{print $4}' filename.csv | more
However, it doesn't work because the first column cantains comma, thus 4th column is not really 4th. Below is an example of a row:
"sdfsdfsd, sfsdf", 454,fgdfg, I_want_this_column,sdfgdg,34546, 456465, etc
Unless you have specific reasons for using awk, I would recommend using a CSV parsing library. Many scripting languages have one built-in (or at least available) and they'll save you from these headaches.
if your first column has quotes always,
$ awk 'BEGIN{ FS="\042[ ]*," } { m=split($2,a,","); print a[3] } ' file
I_want_this_column
if the column you want is always the last 2nd,
$ awk -F"," '{print $(NF-1)}' file
I_want_this_column
You can try this demo script to break down the columns
awk 'BEGIN{ FS="," }
{
for(i=1;i<=NF;i++){
# save normal
if($i !~ /^[ ]*\042|[ ]*\042[ ]*$/){
a[++j]=$i
}
# if quotes at the end
if(f==1 && $i ~ /[ ]*\042[ ]*$/){
s=s","$i
a[++j]=s
#reset
s="";f=0
}
# if quotes in front
if($i ~ /^[ ]*\042/){
s=s $i
f=1
}
if(f==1 && ( $i !~/\042/ ) ){
s=s","$i
}
}
}
END{
# print columns
for(p=1;p<=j;p++){
print "Field "p,": "a[p]
}
} ' file
output
$ cat file
"sdfsdfsd, sfsdf", "454,fgdfg blah , words ", I_want_this_column,sdfgdg
$ ./shell.sh
Field 1 : "sdfsdfsd, sfsdf"
Field 2 : fgdfg blah
Field 3 : "454,fgdfg blah , words "
Field 4 : I_want_this_column
Field 5 : sdfgdg
You shouldn't use awk here. Use Python csv module or Perl Text::CSV or Text::CSV_XS modules or another real csv parser.
Related question -
parse csv file using gawk
If you can't avoid awk, this piece of code does the job you need:
BEGIN {FS=",";}
{
f=0;
j=0;
for (i = 1; i <=NF ; ++i) {
if (f) {
a[j] = a[j] "," $(i);
if ($(i) ~ "\"$") {
f = 0;
}
}
else {
++j;
a[j] = $(i);
if ((a[j] ~ "^\"[^\"]*$")) {
f = 1;
}
}
}
for (i = 1; i <= j; ++i) {
gsub("^\"","",a[i]);
gsub("\"$","",a[i]);
gsub("\"\"","\"",a[i]);
print "i = \"" a[i] "\"";
}
}
Working with CSV files that have quoted fields with commas inside can be difficult with the standard UNIX text tools.
I wrote a program called csvquote to make the data easy for them to handle. In your case, you could use it like this:
csvquote filename.csv | awk 'NR <2 {next}{FS =","}{print $4}' | csvquote -u | more
or you could use cut and tail like this:
csvquote filename.csv | tail -n +3 | cut -d, -f4 | csvquote -u | more
The code and docs are here: https://github.com/dbro/csvquote