سؤال
لدي ملف يسمى "insert.txt". يمكن أن يبدو مثل هذا (أو أقبية):
ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>
وأريد استبدال كتلة من النص في ملف مستهدف (Target.txt) الذي تم تحديده بواسطة "StartStackoverflow" إلى "StopStackoverflow". (أقوم بتبسيط السؤال هنا قليلاً ، لكنه هو نفسه).
البرنامج النصي باش الذي أستخدمه للقيام بذلك هو:
TARGETFILE=target.txt
SOURCEFILE=insert.txt
SOURCETXT="$(<$SOURCEFILE)"
DELIMTXT=$(printf "%q" "$SOURCETXT")
sed -i -e "/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/cSTARTSTACKOVERFLOW\n\n${DELIMTXT}\n\nSTOPSTACKOVERFLOW\n" $TARGETFILE
المشكلة هي أن ما يتم لصقه في "Target.txt" هو في الواقع مقتبس من ANSI-C:
$'ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>'
لاحظ $ '' المضافة.
والسبب هو أن printf "٪ Q" تنتج هذا النمط الاقتباس. أود تجنب ذلك - على الرغم من أنني بحاجة إليه لأنني يجب أن أهرب من كل السوء في هذا الملف.
هل هناك طريقة أفضل للقيام بما سبق باستخدام Bash و SED؟
المحلول
لدى Posix SED أمر "R" للقراءة من ملف. لذا:
sed -i -e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/r large.txt' target.txt
المشكلة الوحيدة هي ما إذا كان يتم قراءة الملف مرة واحدة ، أو مرة واحدة لكل سطر بين خطوط البدء والإيقاف. أظن أنه تتم قراءة مرة واحدة لكل سطر ... والعمل على كيفية رمي الخطوط الإضافية بعيدًا أكثر ... ولكن ربما:
sed -i -e '/STOPSTACKOVERFLOW/r large.txt' \
-e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/d' target.txt
عرض بسيط
يزيل هذا الإصدار علامات البدء والنهاية.
$ cat data
sdasas
adsasdas
start
more
more
end
sdasda
sdasdad
$ cat replace
replace1
replace2
replace3
$ sed -e '/^end$/r replace' -e '/start/,/end/d' data
sdasas
adsasdas
replace1
replace2
replace3
sdasda
sdasdad
الحفاظ على علامات البدء والنهاية
$ cat sedfile
/^end$/{
a\
start
r replace
a\
end
}
/^start$/,/^end$/d
$ sed -f sedfile data
sdasas
adsasdas
start
replace1
replace2
replace3
end
sdasda
sdasdad
$
هذا أمر بديء - لن أحاول القيام بذلك دون استخدام ملف للنص ، ولكن يمكنك القيام بذلك إذا أردت ذلك. انها ليست خط واحد ، رغم ذلك.