各行に 50 文字、50 行のファイルがあります。ファイルの各行には任意の文字が含まれています。文字シーケンス番号 (例: 52) を指定して、*
指定された文字の前に を印刷して適切な文字行を印刷したいと考えています。
答え1
仕様をハードコーディングする場合、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 への最初の呼び出しでは適切な行が選択され、2 回目の呼び出しでは*
適切な列にが挿入されます。
答え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