Tenho um arquivo com 50 caracteres em cada linha e 50 linhas. Cada linha do arquivo contém letras arbitrárias. Quero especificar um número de sequência de caracteres (ex: 52) e imprimir a linha de letras apropriada com um caractere *
impresso na frente do caractere fornecido.
Responder1
Codificando suas especificações, uma maneira seria calcular os números de linhas e colunas a partir do deslocamento (ignorando as novas linhas) e usar esses valores para selecionar a linha adequada e destacar a coluna adequada.
Com um arquivo de entrada in
com 50 linhas assim:
00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
01ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
02ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
03ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
04ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
Então o script a seguir deve fazer aproximadamente o que você pediu:
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
Exemplo de interação:
> 1
*00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
> 2
0*0ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
> 49
00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst*uv
> 50
00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu*v
> 52
0*1ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
> 125
02ABCDEFGHIJKLMNOPQRSTUV*WXYZabcdefghijklmnopqrstuv
A primeira chamada para sed seleciona a linha apropriada, a segunda insere a *
na coluna apropriada.
Responder2
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
É provavelmente a solução mais eficiente porque dd
apenas buscará diretamente o seu deslocamento. Porém, ele não funciona com caracteres largos e pode produzir resultados inesperados com entrada canalizada.
É uma excelente solução com entrada pesquisável na localidade C.
Responder3
Usando GNU ou FreeBSD sed
(para a -r
opção de expressão regular estendida):
Este script vai até o início tanto para as linhas quanto para as posições dos caracteres. se você não quiser que isso aconteça, comente ou exclua a while
linha.
#! /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