How can heredocs be used with xargs?

左心房为你撑大大i 提交于 2019-12-11 04:26:52

问题


Background

I'm looking to strip any # TODO comments from some python source code files output by git archive before sending it off. I'm looking to do so from a script that will be run from a variety of *nix OSes, so it should be as POSIX-compliant as possible.

I'm aware that find -print0 and xargs -0 aren't in the base spec, but they appear to be common enough that I'm fine with using them (unless a better alternative exists). I'm using ed due to sed -i not being in the base spec for in-place editing. Assume the command below is being run from the directory of an already un-tar'd git archive.

I'd be happy with an overall alternative solution for stripping the # TODO comments out, but to satisfy my curiosity I'd also like an answer to the particular problem I'm facing with the command I've come up with.

Existing Code

find . -type f -name "*.py" -print0 | xargs -0 -I {} ed -s {} << 'EOF'
,g/^[ \t]*#[ \t]*TODO/d
,s/[ \t]*#[ \t]*TODO//
w
EOF

Expected Result

All files ending in ".py" are stripped of full lines that only contain TODO comments, or end-of-line comments starting with TODO.

Actual Result

(stdout)

,g/^[ \t]*#[ \t]*TODO/d
,s/[ \t]*#[ \t]*TODO//
w
: No such file or directory

Current Theory

I believe that the << 'EOF' heredoc is being applied to xargs instead of ed, and I'm not sure how to fix that.


回答1:


Fixing the << 'EOF' heredoc direction would take some sh -c trickery that ended up causing even more problems, so I tried re-approaching the problem without requiring heredocs at all.

I ended up landing on:

inline() {
    # Ensure a file was provided
    in="${1?No input file specified}"
    # Create a temp file location
    tmp="$(mktemp /tmp/tmp.XXXXXXXXXX)"
    # Preserve the original file's permissions
    cp -p "$in" "$tmp"
    # Make $@ be the original command
    shift
    # Send original file contents to stdin, output to temp file
    "$@" < "$in" > "$tmp"
    # Move modified temp file to original location, with permissions and all
    mv -f "$tmp" "$in"
}

find . -type f -name "*.py" -exec grep -ilE '#[ \t]*TODO' {} \+ | while read file; do
    inline "$file" sed -e '/^[ \t]*#[ \t]*TODO/ d' -e 's/[ \t]*#[ \t]*TODO//'
done

mktemp isn't technically in the base spec, but appears to be fairly portable so I'm fine including it. ed was also causing me some problems, so I went back to sed with a custom function to replicate the unavailable -i flag for in-place operations.



来源:https://stackoverflow.com/questions/29994643/how-can-heredocs-be-used-with-xargs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!