Печать строки с указанным смещением в файле

Печать строки с указанным смещением в файле

У меня есть файл с 50 символами в каждой строке и 50 строками. Каждая строка файла содержит произвольные буквы. Я хочу указать порядковый номер символа (например: 52) и распечатать соответствующую строку букв с напечатанным *перед заданным символом.

решение1

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

С входным файлом in, содержащим 50 строк, например:

00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
01ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
02ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
03ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
04ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv

Тогда следующий скрипт должен сделать примерно то, что вы просили:

while read -p '> ' n; do
    n=$((n - 1))
    line=$((n / 50 + 1))
    col=$((n % 50))
    <in sed -n -e "${line}p" | sed "s/^.\{${col}\}/&*/g"
done

Пример взаимодействия:

> 1
*00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
> 2
0*0ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
> 49
00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst*uv
> 50
00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu*v
> 52
0*1ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
> 125
02ABCDEFGHIJKLMNOPQRSTUV*WXYZabcdefghijklmnopqrstuv

Первый вызов sed выбирает нужную строку, второй вставляет a *в нужный столбец.

решение2

linemod50(){
        dd bs=51 skip="$(($1/50))" count=1 | {
            dd bs=1 count="$(($1%50-!!($1%50)))"
            IFS= read -r rem
            printf "*%s\n" "$rem"
        }   2 >/dev/null
    }
    i=      forty9=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW
    while   [ "$((i+=1))" -le 50 ]
    do      echo "$((i%10))$forty9"
    done    >file
    linemod50 478 <file

1+0 records in
1+0 records out
51 bytes (51 B) copied, 9.5153e-05 s, 536 kB/s
0abcdefghijklmnopqrstuvwxyz*ABCDEFGHIJKLMNOPQRSTUVW

Это, вероятно, самое эффективное решение dd, поскольку оно просто будет искать напрямую по вашему смещению. Однако оно не работает с широкими символами и может давать неожиданные результаты с конвейерным вводом.

Это превосходное решение с возможностью поиска ввода в локали C.

решение3

Использование GNU или FreeBSD sed(для -rрасширенного варианта регулярного выражения):

Этот скрипт возвращается к началу как строк, так и позиций символов. Если вы не хотите, чтобы он это делал, закомментируйте или удалите строку while.

#! /bin/bash

for O in "$@" ; do
   while [[ "$O" -gt 50 ]] ; do O=$(( $O -50 )) ; done
   O1=$(( $O - 1 ))
   sed -r -n "$O s/^(.{$O1})(.*)/\1\*\2/ p" input.txt
done


$ for i in {1..50} ; do printf "%02i%s\n" "$i" "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv" ; done > input.txt

$ ./offset.sh 3 10 52 100
03*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
10ABCDEFG*HIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
0*2ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
50ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu*v

Связанный контент