Этот код не читает содержимое файла. В сценарии вы получаете имя файла от пользователя и затем сохраняете его в переменной ( $ 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
В настоящее время не существует такого специального инструмента, хотя это довольно легко сделать в 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
Это очень быстрый и простой сценарий. Он не проверяет, пуст файл или нет, поэтому работает только с непустыми файлами.
В вашем примере
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
- количество байтов для перейти к файлу.
Отслеживать просмотренные байты и выдавать текущий номер строки, если заданное смещение находится в пределах суммы:
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;
$perl -0nE 'say substr($_,0,8)=~ y/\n//' ex
2
perl -0nE exp
отбрасывает ввод в $ _
и выполняет exp substr (string, 0,8 )
выбирает первые 8 байтов y / \ n //
удаляет \ n
и возвращает его номер