การใช้ sed เพื่อแทนที่ตัวแปร * large * ในไฟล์


0

ฉันมีล็อกไฟล์จำนวนมากบนกล่อง linux ฉันต้องล้างข้อมูลที่มีความละเอียดอ่อนก่อนส่งให้บุคคลที่สาม ฉันได้ใช้สคริปต์ด้านล่างในครั้งก่อนหน้าเพื่อทำงานนี้และทำงานได้ยอดเยี่ยม (สคริปต์ถูกสร้างขึ้นด้วยความช่วยเหลือจากที่นี่ :-)):

#!/bin/bash

help_text () {
cat <<EOF
Usage: $0 [log_directory] [client_name(s)]
EOF
exit 0
}

CMDLINE=""$0" "$@""
if [ -z "$1" ]; then
        help_text
else

        pattern=""
        delim=""
        n=1

        counter=`find "$1" -name *.gz |sort |wc -l`

        BAKIFS=$IFS
        IFS=$(echo -en "\n\b")
        exec 3<&0
        exec 0<"$2"
        while read -r line
        do
                pattern=$pattern$delim$line
                delim="|"
        done
        exec 0<&3
        IFS=$BAKIFS

        while [ $n -lt $counter ]
        do
                for i in `find "$1" -name *.gz |sort`
                do
                        gunzip "$i"
                        i_unzip=$(echo "$i" |sed 's/\.[^\.]*$//')
                        sed -ri "s/$pattern/CLIENT/g" "$i_unzip"
                        gzip "$i_unzip"
                done
                n=n+1
        done
fi
exit 0

อย่างไรก็ตามตอนนี้หนึ่งในแผนกของเราได้ส่ง CLIENT_FILE.txt ให้ฉันด้วย 425000+ ตัวแปร! ฉันคิดว่าฉันอาจถึงขีด จำกัด ภายในแล้ว! หากใครมีความคิดเกี่ยวกับวิธีการจัดการกับตัวแปรมากมายนี้ฉันขอขอบคุณจริงๆ

ฉันได้ลองแยกไฟล์ไคลเอนต์ออกเป็น 4 โดยมีตัวแปรประมาณ 100,000 รายการในแต่ละตัว แต่ก็ยังใช้งานไม่ได้ ฉันเกลียดที่จะแยกกันอยู่เรื่อย ๆ เพราะฉันมี 20 ไดเรกทอรีที่มีมากถึง 190 ไฟล์ในแต่ละไดเรกทอรีเพื่อให้ทำงานได้ ยิ่งฉันสร้างไฟล์ไคลเอนต์มากเท่าไหร่ก็ยิ่งผ่านมากเท่านั้น


ในล็อกไฟล์ชื่อลูกค้าสามารถปรากฏที่ใดก็ได้หรือคุณเห็นมันในสถานที่ / ฟิลด์ / คอลัมน์ของรายการบันทึก
— glenn jackman

ชื่อลูกค้าสามารถปรากฏที่ใดก็ได้ (หรือไม่เลย) ล็อกไฟล์นั้นยุ่งเหยิงไปหมดจริง ๆ แล้วและฉันก็ไม่รู้ว่าบุคคลที่สามกำลังจะออกจากพวกเขา อย่างไรก็ตามฉันจะไม่ถาม ...
— Steve

คำตอบ:


1

ฉันจะลองแบบนี้:

#!/bin/bash

files=()
while read file; do
    gunzip "$file"  &&  files+=( "${file%.gz}" )
done < <(find "$1" -name '*.gz')

awk '
    FILENAME == ARGV[1] {
        client_name[$0]++
        next
    }
    FNR == 1 {
        output = FILENAME ".new"
    }
    {
        for (i=1; i<=NF; i++) {
            if ($i in client_name)
                $i = "CLIENT"
        }
        print > output
    }
' "$2" "${files[@]}"

for file in "${files[@]}"; do
    mv "$file" "$file.old"  &&
    mv "$file.new" "$file"  &&
    gzip "$file"
done

หากไฟล์บันทึกของคุณมีอะไรมากกว่าเส้นแบ่งพื้นที่อย่างง่ายสคริปต์ awk อาจขัดขวางการจัดรูปแบบ


ดูดี แต่ไม่ชอบบรรทัดที่ 5 ฉันได้ลอง & lt; & lt; และ & lt ;, ตัวเดียว แต่มันบ่นเกี่ยวกับโทเค็นที่ไม่คาดคิดใกล้ & lt; (หรือใกล้ (ในกรณีเดียว & lt;)
— Steve

คุณมีทุบตีรุ่นใด ไวยากรณ์มีความถูกต้อง: เปลี่ยนเส้นทาง stdin (ตัวแรก "& lt;") จาก a การทดแทนกระบวนการ ("& lt; (ค้นหา ... )")
— glenn jackman

แม้ว่าทั้ง sh และ bash ทั้งคู่ไปที่ bash 3.2.51 การรันสคริปต์ด้วย bash อย่างชัดเจนทำให้มันใช้งานได้! ขอบคุณสำหรับความช่วยเหลือของคุณ.
— Steve

สคริปต์ยังใช้งานได้ อย่างมาก รวดเร็ว เร็วกว่าสคริปต์ sed ก่อนหน้าของฉันดังนั้นขอขอบคุณสำหรับสิ่งนั้นด้วย
— Steve

ใช่เมื่อ bash ถูกเรียกเป็น "sh" มันจะพยายามทำงานใน "POSIX mode" ดังนั้นคุณสมบัติทุบตีที่มีประโยชน์มากมายจะถูกปิดการใช้งาน ตรวจสอบหน้าคน
— glenn jackman

0

คุณควรพยายามเขียน sed รูปแบบเป็นไฟล์และส่งผ่านไปยัง sed ด้วยตัวเลือก --file=. พารามิเตอร์บรรทัดคำสั่งไม่ได้หมายถึงการส่งผ่านข้อมูลจำนวนมาก

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