Drucken einer Zeile an einem angegebenen Offset in einer Datei

Drucken einer Zeile an einem angegebenen Offset in einer Datei

Ich habe eine Datei mit 50 Zeichen pro Zeile und 50 Zeilen. Jede Zeile der Datei enthält beliebige Buchstaben. Ich möchte eine Zeichenfolgenummer angeben (z. B. 52) und die entsprechende Buchstabenzeile mit einem *vor dem angegebenen Zeichen ausdrucken lassen.

Antwort1

Wenn Sie Ihre Angaben fest codieren, besteht eine Möglichkeit darin, die Zeilen- und Spaltennummern aus dem Offset zu berechnen (unter Ignorierung von Zeilenumbrüchen) und diese Werte zu verwenden, um die richtige Zeile auszuwählen und die richtige Spalte hervorzuheben.

Mit einer Eingabedatei invon 50 Zeilen wie diesen:

00ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
01ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
02ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
03ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv
04ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv

Dann sollte das folgende Skript ungefähr das tun, was Sie gefragt haben:

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

Beispielinteraktion:

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

Der erste Aufruf von sed wählt die entsprechende Zeile aus, der zweite fügt ein _ *in der entsprechenden Spalte ein.

Antwort2

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

Dies ist wahrscheinlich die effizienteste Lösung dd, da direkt zu Ihrem Offset gesucht wird. Es funktioniert jedoch nicht mit Breitzeichen und kann bei Pipe-Eingaben zu unerwarteten Ergebnissen führen.

Es handelt sich um eine hervorragende Lösung mit suchbarer Eingabe im C-Gebietsschema.

Antwort3

Verwendung von GNU oder FreeBSD sed(für die -rOption für erweiterte reguläre Ausdrücke):

Dieses Skript springt sowohl für die Zeilen als auch für die Zeichenpositionen zurück zum Anfang. Wenn Sie das nicht möchten, kommentieren Sie die whileZeile aus oder löschen Sie sie.

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

verwandte Informationen