แทนที่เนื้อหากลุ่มการจับภาพ regex โดยใช้ sed


16

ฉันพยายามแก้ไขไฟล์ nginx.conf ของฉันโดยทางโปรแกรมซึ่งมีบรรทัดดังนี้:

        access_log /var/log/nginx/access.log;

ซึ่งฉันต้องการให้มีลักษณะเช่นนี้:

        access_log /dev/stdout;

ฉันเชื่อว่า regex ^\s*access_log([^;]*);จะจับ/var/log/nginx/access.logส่วนหนึ่งในกลุ่มการดักจับ แต่ฉันไม่แน่ใจว่าจะแทนที่กลุ่มการจับภาพด้วย sed ได้อย่างไร

ฉันได้พยายาม

echo "        access_log /var/log/nginx/access.log;" | sed 's/^\s*access_log([^;]*);/\1\\\/dev\\\/stdout/'

แต่ฉันได้รับข้อผิดพลาด:

sed: -e expression #1, char 45: invalid reference \1 on `s' command's RHS

ถ้าฉันลองsed -rแล้วไม่มีข้อผิดพลาด แต่ผลลัพธ์ไม่ใช่สิ่งที่ฉันคาดหวัง:

 /var/log/nginx/access.log\/dev\/stdout

ฉันพยายามฉลาดด้วยกลุ่มจับภาพและไม่สนใจและค้นหาคำว่า "access_log /var/log/nginx/access.log โดยตรง" ในกรณีที่การกระจายเปลี่ยนตำแหน่งไฟล์บันทึกเริ่มต้น


1
sed '/access_log/s|/[^;]\+|/dev/stdout|'
Costas

@Costas หากคุณจะตอบว่าฉันตอบ upvote คุณตามที่ใช้งานได้!
Abe Voelker

คำตอบ:


16

ความผิดพลาดสองสามข้อที่นั่น

ก่อนอื่นเนื่องจากsedใช้นิพจน์ทั่วไปพื้นฐานคุณต้องใช้\(และ\)สร้างกลุ่มการจับภาพ -rสวิตช์ช่วยให้การแสดงออกปกติขยายซึ่งเป็นเหตุผลที่คุณไม่ได้รับข้อผิดพลาด ดูเหตุใดฉันจึงต้องหลีกเลี่ยงอักขระ regex ใน sed เพื่อตีความเป็นอักขระ regex .

ประการที่สองคุณวางกลุ่มการดักจับในตำแหน่งที่ผิด ถ้าฉันเข้าใจคุณอย่างถูกต้องคุณสามารถทำสิ่งนี้:

sed -e 's!^\(\s*access_log\)[^;]*;!\1 /dev/stdout;!' your_file

หมายเหตุ: ใช้!เป็นตัวคั่น regex /dev/stdoutเพื่อหลีกเลี่ยงการหลบหนีทับใน


ขอบคุณใช้งานได้อย่างยอดเยี่ยม! ฉันยังไม่สามารถทำเครื่องหมายว่าเป็นที่ยอมรับได้ แต่จะกลับมาอีกครั้งภายใน 9 นาที
Abe Voelker

1
@AbeVoelker คุณยินดีอย่างมาก ฉันดีใจที่ฉันสามารถช่วย
โจเซฟอาร์

5

ใน regexp ของคุณคุณควรรู้ว่า\No.เป็นอ้างอิงกลับมา()กับรูปแบบในวงเล็บ ดังนั้น regexp ควรเป็น's@^(\s*access_log ).*$@\1/dev/stdout/;@'

ฉันสามารถนำเสนอ

sed '/access_log/s|/[^;]\+|/dev/stdout|'

คำแนะนำ: ไม่ว่าคุณตั้งใจจะใช้/ภายใน patern คุณมีอิสระที่จะเปลี่ยนs///สำหรับทุกสัญลักษณ์ที่คุณต้องการs###เช่น


ขอบคุณฉันหวังว่าฉันจะตอบได้สองคำตอบ! ฉันไม่เสียใจที่ไม่ได้อ่าน man pages อย่างเต็มที่อีกต่อไปก่อนที่จะขอความช่วยเหลือหลังจากได้เห็นวิธีแก้ปัญหา
Abe Voelker

3

แทนที่จะจับมันทำไมไม่เพียงแค่หามันและทำการทดแทน? เช่น:

sed "/access_log/ s| /.*;| /dev/stdout;|"

มันจะค้นหาบรรทัดที่ตรงกับ " access_log" จากนั้นในบรรทัดใด ๆ ที่จะแทนที่ " /whatever/path/is/there;" ด้วย " /dev/stdout;"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.