0

I have working shell (not bash) code, that splits string to varialbes:

sh """
version='1.2.3.4'

echo \$version | { IFS=. read a b c d; echo \$a; }

echo \"a\" \$a
"""

Here is output:

+ version=1.2.3.4
+ IFS=. read a b c d
+ echo 1.2.3.4
+ echo 1
1
+ echo a
a

Problem:

I can't access values of a,b,c,d outside braces

Question:

How can I access these variables?


UPD:

I run this code via jenkins pipeline, which let me use such approach. If I try to use another one, it just ignores attempt to parse string:

stage('test') {
    steps {
        sh """
        version='1.2.3.4'

        IFS=. read a b c d <<EOF
        \$version
        EOF

        echo \"a\" \$a
        """
    }
}

Output:

[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (test)
[Pipeline] sh
[ScpPipeline] Running shell script
+ version=1.2.3.4
+ IFS=. read a b c d
[Pipeline] }

UPD_1:

Problem was in spaces and tabs... 0_o So this is working variant (but ugly):

stage('test') {
    steps {
sh """
version='1.2.3.4'

IFS=. read a b c d <<EOF
\$version
EOF

echo \"a\" \$a \"b\" \$b \"c\" \$c \"d\" \$d
"""
    }
}
mohax
  • 4,435
  • 2
  • 38
  • 85
  • 3
    It is because it is defined in a sub-shell, everything after `|` is run is child shell and especially the variable assignments are lost – Inian Jan 10 '18 at 18:25
  • 2
    [BashFAQ/024](https://mywiki.wooledge.org/BashFAQ/024): "I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?" – Benjamin W. Jan 10 '18 at 18:39
  • Thanks, but using `{}` is the only way for me to split string... I tryed different ways, but nothing work if I insert `shell` code as part of `jenkins` `pipeline`( – mohax Jan 10 '18 at 20:01
  • No; using `{}` is not the only way to split the string. There are many other ways to do it, some built-in to Bash, others invoking external programs. – Jonathan Leffler Jan 10 '18 at 20:12
  • @JonathanLeffler, I found the main problem - there were spaces and tabs in my code. They broke everething) Now it works, but code looks bad – mohax Jan 10 '18 at 20:20

1 Answers1

2

Use a here document instead of a pipe.

sh """
version='1.2.3.4'

IFS=. read a b c d <<EOF
\$version
EOF

echo \"a\" \$a
"""
chepner
  • 497,756
  • 71
  • 530
  • 681
  • 1
    Do you think I should dupe this - https://stackoverflow.com/questions/16854280/a-variable-modified-inside-a-while-loop-is-not-remembered? I don't see why not. I thought since you've answered it, may be you had a good reason not to – Inian Jan 10 '18 at 18:26
  • Sure; most of the time, I'm just too lazy to look for a dupe when it would be faster to just write an answer. In this case, I was thinking there might be something specific to the Jenkins context, but there really isn't. – chepner Jan 10 '18 at 19:50
  • Please, see updated answer. I try to run your code, but it's ignored. I run it as step of `jenkins` `pipline` and there are a lot of limitations( – mohax Jan 10 '18 at 19:59
  • 1
    You can't indent the here-document, at least not with arbitrary whitespace. – chepner Jan 10 '18 at 20:03
  • @chepner, omg! Your code work correct, if I remove all tabs and spaces in script! Thank you! Do you have any idea how to avoid removing all spaces and tabs? – mohax Jan 10 '18 at 20:15
  • 1
    Actually, you can indent the *contents* here, since `read` will strip any leading whitespace. If you switch from `<<` to `<<-`, you can indent the delimiter with *tabs only* and it will work. – chepner Jan 10 '18 at 21:19