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 in
von 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 -r
Option 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 while
Zeile 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