Скрипт Bash для отображения всех IP-адресов в префиксе

Чтобы обрабатывать файл по строкам, вам просто нужно отделить чтение файла и код, который действует на этот вход. Вы можете выполнить это, буферизируя ввод, пока не нажмете новую строку. Предполагая, что у нас есть один объект JSON на строку (в основном, формат B):

var stream = fs.createReadStream(filePath, {flags: 'r', encoding: 'utf-8'});
var buf = '';

stream.on('data', function(d) {
    buf += d.toString(); // when data is read, stash it in a string buffer
    pump(); // then process the buffer
});

function pump() {
    var pos;

    while ((pos = buf.indexOf('\n')) >= 0) { // keep going while there's a newline somewhere in the buffer
        if (pos == 0) { // if there's more than one newline in a row, the buffer will now start with a newline
            buf = buf.slice(1); // discard it
            continue; // so that the next iteration will start with data
        }
        processLine(buf.slice(0,pos)); // hand off the line
        buf = buf.slice(pos+1); // and slice the processed data off the buffer
    }
}

function processLine(line) { // here's where we do something with a line

    if (line[line.length-1] == '\r') line=line.substr(0,line.length-1); // discard CR (0x0D)

    if (line.length > 0) { // ignore empty lines
        var obj = JSON.parse(line); // parse the JSON
        console.log(obj); // do something with the data here!
    }
}

Каждый раз, когда поток файлов принимает данные из файловой системы, он помещается в буфер, а затем вызывается pump .

Если в буфере нет новой строки, pump просто возвращается, ничего не делая. Дополнительные данные (и, возможно, новая строка) будут добавлены в буфер в следующий раз, когда поток получит данные, а затем у нас будет полный объект.

Если есть новая строка, pump срезает буфер от начала до новой строки и передать его на process. Затем он снова проверяет, есть ли в буфере новая строка (цикл while). Таким образом, мы можем обрабатывать все строки, которые были прочитаны в текущем фрагменте.

Наконец, process вызывается один раз для каждой строки ввода. Если он присутствует, он удаляет символ возврата каретки (чтобы избежать проблем с концами строк & ndash; LF vs CRLF), а затем вызывает JSON.parse одну строку. На этом этапе вы можете делать все, что вам нужно, с вашим объектом.

Обратите внимание, что JSON.parse строго относится к тому, что он принимает в качестве входных данных; вы должны указывать ваши идентификаторы и строковые значения с двойными кавычками . Другими словами, {name:'thing1'} выдаст ошибку; вы должны использовать {"name":"thing1"}.

Поскольку за один раз в памяти будет больше, чем кусок данных, это будет чрезвычайно эффективным с точки зрения памяти. Это также будет очень быстро. Быстрый тест показал, что я обработал 10 000 строк в возрасте до 15 мс.

13
задан Fredrik Pihl 7 June 2013 в 14:47
поделиться

1 ответ

Этот сценарий должен сделать. Это - (почти) чистый Удар. seq часть может быть заменена, если абсолютно чистый удар требуется.

, Так как Удар, по-видимому, использует подписанные 4-байтовые целые числа с двумя дополнениями, сценарий ограничен/8 максимумом маски. Я нашел диапазоны больше, чем/16 непрактичный так или иначе, таким образом, это не беспокоит меня вообще. Если кто-то знает простой способ преодолеть это, разделите:)

#!/usr/bin/env bash

base=${1%/*}
masksize=${1#*/}

[ $masksize -lt 8 ] && { echo "Max range is /8."; exit 1;}

mask=$(( 0xFFFFFFFF << (32 - $masksize) ))

IFS=. read a b c d <<< $base

ip=$(( ($b << 16) + ($c << 8) + $d ))

ipstart=$(( $ip & $mask ))
ipend=$(( ($ipstart | ~$mask ) & 0x7FFFFFFF ))

seq $ipstart $ipend | while read i; do
    echo $a.$(( ($i & 0xFF0000) >> 16 )).$(( ($i & 0xFF00) >> 8 )).$(( $i & 0x00FF ))
done 

Использование:

./script.sh 192.168.13.55/22

Проверенный с версией 4.4.23 Удара. YMMV.

0
ответ дан 1 December 2019 в 17:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: