问题
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