How to pipe a here-document through a command and

2019-03-12 13:58发布

Right now this outputs the value I need on stdout. How can I capture it into a variable so I can use it in the rest of the script?

Requirements:

  • The script needs to be all in one file.
  • I'd prefer not to write any temp files, if possible.

.

#!/bin/bash

cat << EOF | xsltproc - ../pom.xml | tail -1
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/"><xsl:value-of select="/project/version"/></xsl:template>
</xsl:stylesheet>
EOF

3条回答
贼婆χ
2楼-- · 2019-03-12 14:09

This seems to work (based on Ignacio's answer). By using a subshell the here-document is correctly piped into xsltproc while still being passed through tail after.

VERSION=$((xsltproc - ../pom.xml | tail -1) << EOF
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/"><xsl:value-of select="/project/version"/></xsl:template>
</xsl:stylesheet>
EOF
)
查看更多
时光不老,我们不散
3楼-- · 2019-03-12 14:32

The cat ... | isn't necessary.

foo=$(sed 's/-/_/g' << EOF
1-2
3-4
EOF
)
查看更多
够拽才男人
4楼-- · 2019-03-12 14:33

I've been playing around with heredocs for a week or two. Here's an excerpt from my answer to Is there a way to get actual (uninterpreted) shell arguments in a function or script? at Unix Stack Exchange that might help illustrate their use a little for your case:

... EXCERPT: ...

Probably you noticed the difference between the two heredocs in the second example. The heredoc EOF terminator within the function is unquoted, while the one fed to read is quoted with single quotes. In this way the shell is instructed to perform expansion on the heredoc with an unquoted terminator, but not to do so when its terminator is quoted. It doesn't break when expanding the unquoted heredoc in the function because the value of the variable it expands is already set as a quoted string and it doesn't parse it twice.

Probably what you want to do involves piping your Windows path from the output of one command into the input of another dynamically. Command substitution within a heredoc makes this possible:

% _stupid_mspath_fix() { 
> sed -e 's@\\@/@g' -e 's@\(.\):\(.*\)@/drive/\1\2@' <<_EOF_
>> ${1}
>> _EOF_
> }
% read -r _stupid_mspath_arg <<'_EOF_'                    
> c:\some\stupid\windows\place
> _EOF_
% _stupid_mspath_fix ${_stupid_mspath_arg}
/drive/c/some/stupid/windows/place    
% read -r _second_stupid_mspath_arg <<_EOF_                    
> $(printf ${_stupid_mspath_arg})
> _EOF_
% _stupid_mspath_fix ${_second_stupid_mspath_arg}
/drive/c/some/stupid/windows/place

So basically if you can reliably output the backslashes from some application (I used printf above), then running that command within $(...) and enclosing that within an unquoted heredoc passed to another application that can reliably accept the backslashes as input (such as read and sed above) will bypass the shell's parsing of your backslashes altogether. Whether or not the applications can handle the backslashes as input/output is something you'll have to find out for yourself.

-Mike

查看更多
登录 后发表回答