การใช้ 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.