ฉันต้องเพิ่มบรรทัดต่อไปนี้ที่ส่วนท้ายของไฟล์ปรับแต่ง:
include "/configs/projectname.conf"
ไปยังไฟล์ที่เรียกว่า lighttpd.conf
ฉันกำลังมองหาที่sed
จะใช้ในการทำเช่นนี้ แต่ฉันไม่สามารถหาวิธีได้
ฉันจะแทรกได้อย่างไรถ้าบรรทัดนั้นไม่มีอยู่?
ฉันต้องเพิ่มบรรทัดต่อไปนี้ที่ส่วนท้ายของไฟล์ปรับแต่ง:
include "/configs/projectname.conf"
ไปยังไฟล์ที่เรียกว่า lighttpd.conf
ฉันกำลังมองหาที่sed
จะใช้ในการทำเช่นนี้ แต่ฉันไม่สามารถหาวิธีได้
ฉันจะแทรกได้อย่างไรถ้าบรรทัดนั้นไม่มีอยู่?
คำตอบ:
เพียงทำให้มันง่าย :)
grep + echoควรเพียงพอ:
grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
-q
เงียบสงบ-x
ตรงกับทั้งบรรทัด-F
pattern เป็นสตริงธรรมดาแก้ไข: รวมคำแนะนำ @cerin และ @ thijs-woutersไว้
grep -vq ...
echo
เพื่อเรียกcat
heredoc หลายอันลงในไฟล์ปรับแต่ง
-s
เพื่อละเว้นข้อผิดพลาดเมื่อไม่มีไฟล์สร้างไฟล์ใหม่ที่มีเพียงบรรทัดนั้น
นี่จะเป็นโซลูชันที่สะอาดอ่านได้และใช้ซ้ำได้โดยใช้grep
และecho
เพื่อเพิ่มบรรทัดลงในไฟล์ต่อเมื่อไม่มีอยู่:
LINE='include "/configs/projectname.conf"'
FILE='lighttpd.conf'
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
หากคุณต้องการให้ตรงกับการใช้งานทั้งบรรทัด grep -xqF
เพิ่ม-s
เพื่อละเว้นข้อผิดพลาดเมื่อไม่มีไฟล์สร้างไฟล์ใหม่ที่มีเพียงบรรทัดนั้น
sudo grep -qF "$LINE" "$FILE" || echo "$LINE" | sudo tee -a "$FILE"
-
นี้ที่จริงไม่ทำงานเมื่อเส้นเริ่มต้นด้วย
--
ในคำสั่ง grep ดังนั้นมันจะไม่ตีความ $ LINE ที่เริ่มต้นด้วยเส้นประเป็นตัวเลือกอีกต่อไป
นี่คือsed
รุ่น:
sed -e '\|include "/configs/projectname.conf"|h; ${x;s/incl//;{g;t};a\' -e 'include "/configs/projectname.conf"' -e '}' file
หากสตริงของคุณอยู่ในตัวแปร:
string='include "/configs/projectname.conf"'
sed -e "\|$string|h; \${x;s|$string||;{g;t};a\\" -e "$string" -e "}" file
sed -i -e '\|session.*pam_mkhomedir.so|h; ${x;s/mkhomedir//;{g;tF};a\' -e 'session\trequired\tpam_mkhomedir.so umask=0022' -e '};:F;s/.*mkhomedir.*/session\trequired\tpam_mkhomedir.so umask=0022/g;' /etc/pam.d/common-session
sed
หลายปี แต่ส่วนใหญ่เป็นเพียงs
คำสั่ง hold
และpattern
แลกเปลี่ยนพื้นที่อยู่นอกเหนือฉัน
ถ้าเขียนไปยังแฟ้มที่มีการป้องกันและ @drAlberT @ rubo77 's คำตอบอาจจะไม่ทำงานสำหรับคุณตั้งแต่หนึ่งไม่สามารถ >>
sudo วิธีง่ายๆในทำนองเดียวกันแล้วจะใช้tee --append
(หรือบน MacOS, tee -a
):
LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF "$LINE" "$FILE" || echo "$LINE" | sudo tee --append "$FILE"
ถ้าวันหนึ่งมีคนอื่นต้องจัดการกับรหัสนี้เป็น "รหัสดั้งเดิม" ดังนั้นบุคคลนั้นจะรู้สึกขอบคุณถ้าคุณเขียนรหัสที่น้อยกว่าเช่น
grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi
โซลูชัน sed อื่นคือการผนวกท้ายบรรทัดสุดท้ายและลบโซลูชันที่มีอยู่ก่อนเสมอ
sed -e '$a\' -e '<your-entry>' -e "/<your-entry-properly-escaped>/d"
"escaped อย่างถูกต้อง" หมายถึงการใส่ regex ที่ตรงกับรายการของคุณนั่นคือหนีการควบคุม regex ทั้งหมดจากรายการจริงของคุณเช่นใส่แบ็กสแลชต่อหน้า ^ $ / *? + ()
สิ่งนี้อาจล้มเหลวในบรรทัดสุดท้ายของไฟล์ของคุณหรือหากไม่มีการขึ้นบรรทัดใหม่ฉันไม่แน่ใจ แต่สามารถจัดการได้โดยการแยกสาขาที่ดี ...
sed -i.bak -e '$a\' -e "$NEW_IP\t\t$HOST.domain\t$HOST" -e "/.*$HOST/d" /etc/hosts
sed -i -e '/<entry>/d; $a <entry>'
d
คำสั่งจะรีสตาร์ทโปรแกรม sed ดังนั้นจึงข้ามa
ppend หากการลบเกิดขึ้นที่บรรทัดสุดท้าย
a
ppend จะต้องมีการดำเนินการก่อนหนึ่งคำ:d
sed -i -e '$a<entry>' -e '/<entry>/d'
มันเกือบจะเหมือนกันกับคำตอบเดิมของคุณ
ใช้ awk
awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file
file file
เพราะมันทำสองผ่านผ่านไฟล์เดียวกัน NR==FNR
เป็นจริงในการผ่านครั้งแรก แต่ไม่ใช่ครั้งที่สอง นี่เป็นสำนวน Awk ทั่วไป
คำตอบที่ใช้ grep นั้นผิด คุณต้องเพิ่มตัวเลือก -x เพื่อจับคู่ทั้งบรรทัดมิฉะนั้นบรรทัดที่ต้องการ#text to add
จะยังคงตรงกันเมื่อต้องการเพิ่มtext to add
จะยังคงตรงกับเมื่อมองหาเพื่อเพิ่มว่า
ดังนั้นวิธีแก้ไขปัญหาที่ถูกต้องคือ:
grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
การใช้ sed:มันจะแทรกที่ท้ายบรรทัด คุณสามารถส่งผ่านตัวแปรได้ตามปกติ
grep -qxF "port=9033" $light.conf
if [ $? -ne 0 ]; then
sed -i "$ a port=9033" $light.conf
else
echo "port=9033 already added"
fi
ใช้ oneliner sed
grep -qxF "port=9033" $lightconf || sed -i "$ a port=9033" $lightconf
ใช้เสียงสะท้อนอาจไม่ทำงานภายใต้รูท แต่จะทำงานเช่นนี้ แต่จะไม่ยอมให้คุณทำสิ่งต่าง ๆ โดยอัตโนมัติหากคุณต้องการทำเพราะอาจขอรหัสผ่าน
ฉันมีปัญหาเมื่อฉันพยายามแก้ไขจากรูทสำหรับผู้ใช้เฉพาะ การเพิ่ม$username
ก่อนหน้าเป็นการแก้ไขสำหรับฉัน
grep -qxF "port=9033" light.conf
if [ $? -ne 0 ]; then
sudo -u $user_name echo "port=9033" >> light.conf
else
echo "already there"
fi
ฉันต้องการที่จะแก้ไขไฟล์ที่มีสิทธิ์ในการเขียนที่ถูก จำกัด sudo
จำเป็นเพื่อ ทำงานจากคำตอบของ ghostdog74 และใช้ไฟล์ temp:
awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file > /tmp/file
sudo mv /tmp/file file
crudini
อาจเป็นตัวเลือกที่ดี (แต่ไม่ใช่สำหรับ lighthttpd)