Imprimir una línea en un desplazamiento específico en un archivo

Imprimir una línea en un desplazamiento específico en un archivo

Tengo un archivo con 50 caracteres en cada línea y 50 líneas. Cada línea del archivo contiene letras arbitrarias. Quiero especificar un número de secuencia de caracteres (por ejemplo, 52) e imprimir la línea de letras adecuada con un *impreso delante del carácter dado.

Respuesta1

Codificando sus especificaciones, una forma sería calcular los números de línea y columna a partir del desplazamiento (ignorando las nuevas líneas) y usar esos valores para seleccionar la línea adecuada y resaltar la columna adecuada.

Con un archivo de entrada inde 50 líneas como este:

00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
01ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
02ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
03ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
04ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv

Entonces el siguiente script debería hacer aproximadamente lo que usted pidió:

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

Ejemplo de interacción:

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

La primera llamada a sed selecciona la línea adecuada, la segunda inserta a *en la columna adecuada.

Respuesta2

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

Probablemente sea la solución más eficiente porque ddsimplemente buscará directamente hasta su compensación. Sin embargo, no funciona con caracteres anchos y puede producir resultados inesperados con entradas canalizadas.

Es una excelente solución con entrada buscable en la configuración regional C.

Respuesta3

Usando GNU o FreeBSD sed(para la -ropción de expresión regular extendida):

Este script regresa al principio tanto para las líneas como para las posiciones de los caracteres. Si no desea que haga eso, comente o elimine la whilelínea.

#! /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

información relacionada