4 ms·
Shell Builtin ‘eval’
- jagrsw 5y agoChallenge accepted :) $ echo lorem ipsum > "foo bar" $ cmd='cat "foo bar"' $ trap "$cmd" ERR;test;trap - ERR lorem ipsum
- jeffrallen 5y agoI recently had to use eval to solve a shell scripting problem. During the same task, I also discovered that a for loop on it's own is run inside the same shell as the code around it (duh), but a for loop which is feeding a pipe is run in a subshell. This was a surprise, because I wanted to set some variables in the for loop, piping progress indications to the `dialog` program, and then use those variables afterwards. My variables kept disappearing after the for loop exited, but not when I removed the progress indications. Shell sucks.
- aaaaaaaaaaab 5y agoHehe. Rookie mistake. This is how you do it: i=0 for foo in …; do i=((i + 1)) done > >(stuff | goes | here)
- _0w8t 5y agoThis uses Bash extension not available in POSIX. Bash also has lastpipe shopt that helps when one needs to read from a process. To stay compatible with POSIX one needs to use either named pipes or extra file discriptors to communicate from the sub shell.
- aaaaaaaaaaab 5y agoYeah, but in my experience limiting yourself to the POSIX sh feature set is almost always just nitpicking. Bash is ubiquitous enough that this is hardly a problem in practice.
- _0w8t 5y agoIn my opinion the moment POSIX shell is not enough, one better use more appropriate language than learning all Bash-specific syntax rules and exceptions. And with containers bash may not be even there.
- aaaaaaaaaaab 5y agoWhich language would be better than bash for building concurrent pipelines from other utilities? Sure, you can build pipelines in Python via the subprocess module, but it’s not exactly an ergonomic API…
- mkdirp 5y agoYou can use arrays. $ ls -la "foo bar" -rw------- 1 u0_a298 u0_a298 6 Jan 10 00:22 'foo bar' $ cmd=(cat "foo bar") $ "${cmd[@]}" hello Edit, since someone pointed out you the article is using dash, something I overlooked, you can still avoid eval by using set to overload the script args: $ set -- cat "foo bar" $ "$@" hello Not sure how this would work if you still need the values of the current args. I don't think there is a way set a variable to be the current "$@" to be used later. However, if you don't need the current args any more, this is a possible solution to avoid eval.