Получить номер строки из байтового смещения

Этот код не читает содержимое файла. В сценарии вы получаете имя файла от пользователя и затем сохраняете его в переменной ( $ file и позже $ mystring ).

Когда вы запускаете для токена в $ mystring , вы просматриваете содержимое переменной $ mystring в виде списка, но в нем есть только имя файла, введенное пользователем. . Итак, все команды, ссылающиеся на $ token , управляют строкой, которую вы получили от своего пользователя.

Чтобы управлять содержимым файла, вы можете использовать cat , как указано @faadi: mystring = $ (cat $ file) .

РЕДАКТИРОВАТЬ:

Просто поправлю что-то в ответе. Я сосредоточился на том, чтобы вы не читали файл, и не смог решить еще одну проблему, поднятую @steeldriver в его комментарии. Если вы просто измените строку с mystring = $ file на mystring = $ (cat $ file) , вы все равно не добьетесь того, чего хотите, потому что в конечном итоге вы разделите содержимое файл в списке и запустив wc над ними.

Вы можете удалить цикл for, используя это (если вы хотите сохранить текст в переменной и использовать echo ):

#!/bin/bash

echo "File to read:"
read file
mystring=$(cat $file)
echo ""
echo "TEXT:"
echo "$mystring"
echo ""
echo -n "Lines: "
echo "$mystring" | wc -l
echo -n "Words: "
echo "$mystring" | wc -w
echo -n "Chars: "
echo "$mystring" | wc -c

Или, как предлагает @steeldriver, просто перенаправить файл на STDIN wc , например:

#!/bin/bash

echo "File to read:"
read file
echo ""
echo "TEXT:"
cat $file
echo ""
echo -n "Lines: "
wc -l < $file
echo -n "Words: "
wc -w < $file
echo -n "Chars: "
wc -c < $file
12
31.01.2017, 21:13
4 ответа

В настоящее время не существует такого специального инструмента, хотя это довольно легко сделать в python:

#!/usr/bin/env python3
import sys
import os

offset = int(sys.argv[2])
newline = 1
with open(sys.argv[1]) as fd:
    fd.seek(offset)
    while True:
        try:
            byte = fd.read(1)
            if byte == '\n': newline+=1
            #print(byte)
            offset = offset - 1
            fd.seek(offset)
        except ValueError:
            break
print(newline)

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

line4byte.py <FILE> <BYTE>

Тестовый запуск:

$ cat input.txt
001
002
003
004
$ chmod +x ./line4byte.py                                                     
$ ./line4byte.py input.txt 8                                                  
3

Это очень быстрый и простой сценарий. Он не проверяет, пуст файл или нет, поэтому работает только с непустыми файлами.

4
27.01.2020, 19:54

В вашем примере

001
002
003
004

байт номер 8 является вторым символом новой строки, а не 0 в следующей строке.

Следующее даст вам количество полных строк после $ b байтов:

$ dd if=data.in bs=1 count="$b" | wc -l

Он сообщит 2 с b , установленным на 8, и это сообщит 1 с b , установленным на 7.

Утилита dd , как она здесь используется, будет читать данные из файла . в , и будет читать блоки $ b размером 1 байт.

Как правильно указывает icarus в комментариях ниже, использование bs = 1 неэффективно. В данном конкретном случае более эффективно поменять местами bs и count :

$ dd if=data.in bs="$b" count=1 | wc -l

Это будет иметь тот же эффект, что и первая команда dd , но будет читать только один блок из $ b байт.

Утилита wc считает новые строки, а «строка» в Unix всегда заканчивается новой строкой. Таким образом, указанная выше команда по-прежнему будет говорить 2 , если вы установите для b значение меньше 12 (следующая новая строка). Таким образом, результат, который вы ищете, - это любое число, указанное в вышеуказанных отчетах конвейера, плюс 1.

Это, очевидно, также будет учитывать случайные символы новой строки в двоичной части вашего файла, которая предшествует тексту ASCII. Если бы вы знали, где начинается бит ASCII, вы могли бы добавить skip = "$ offset" к команде dd , где $ offset - количество байтов для перейти к файлу.

17
27.01.2020, 19:54

Отслеживать просмотренные байты и выдавать текущий номер строки, если заданное смещение находится в пределах суммы:

perl -E '$off=shift;while(<>){$sum+=length;if($sum>=$off){say $.;exit}}' 8 file

Или по длине:

#!/usr/bin/env perl
use strict;
use warnings;
die "Usage: $0 offset file|-\n" if @ARGV != 2;
my $offset = shift;
shift if $ARGV[0] eq '-';
my $sum;
while (readline) {
    $sum += length;
    if ($sum >= $offset) {
        print "$.\n";
        exit;
    }
}
exit 1;
4
27.01.2020, 19:54
$perl -0nE 'say substr($_,0,8)=~ y/\n//'  ex
2
  • perl -0nE exp отбрасывает ввод в $ _ и выполняет exp
  • substr (string, 0,8 ) выбирает первые 8 байтов
  • y / \ n // удаляет \ n и возвращает его номер
3
27.01.2020, 19:54

Теги

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