I have a bunch of files named like this:
chapter1.tex
chapter2.tex
chapter3.tex
...
chapter 10.tex
chapter 11.tex
etc.
I am trying to use sed to find and replace the first instance of AAAAAA with ZZZZZZ within all of the files.
sed -i "0,/AAAAAA/s//ZZZZZZ/" chapter*.tex
I tried this above command, but there are two problems:
AAAAAA within each file. I want only the first instance among all files.ls then chapter10.tex is listed before chapter1.tex. It is critical it searches the files in order of the chapters.How to use Bash tools to find and replace first instance, from among a large list of files, so only the first instance in the first found file is replaced, while also respecting the file order (chapter1.tex is first, chapter10.tex is tenth)?
With the complete GNU toolchest you don't need a loop.
printf '%s\0' chapter*.tex \
| sort -zV \
| xargs -0 grep -FlZ 'AAAAAA' \
| head -zn1 \
| xargs -0r sed -i 's/AAAAAA/ZZZZZZ/'
Here is a bash loop based solution that will work with filenames such as chapter 10.tex i.e. filenames with spaces etc:
while IFS= read -r -d '' file; do
if grep -q 'AAAAAA' "$file"; then
echo "changing $file"
sed -i '0,/AAAAAA/s//ZZZZZZ/' "$file"
break
fi
done < <(printf '%s\0' chapter*.tex | sort -z -V)
This is assuming both sed and sort are from gnu utils.
If you have gnu awk 4+ version that supports in-place editing i.e. -i inplace then you can replace grep + sed with single awk:
while IFS= read -r -d '' file; do
awk -i inplace '!n {n=sub(/AAAAAA/, "ZZZZZZ")} 1;
END {exit !n}' "$file" && break
done < <(printf '%s\0' chapter*.tex | sort -z -V)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With