ファイルの特定の行範囲を印刷するには、次のbash関数を使用しています。
print-lines ()
{
na=$1
nb=$2
dir=$3
find "$dir" \( -name \*.org -o -name \*.texi \) \
-exec awk -v a="$na" -v b="$nb" \
'FNR >= a && FNR <= b {print}' {} +
}
このファイルは2つあります。
foo:
a
b
c
d
e
bar:
1
2
3
4
5
コマンドをprint-lines 2 4
。私が望む結果は
==> foo <==
b
c
d
==> bar <==
2
3
4
答え1
ファイルに少なくとも1行がある場合にのみ$na
ファイル名を印刷する必要がある場合:
find . -name '*.csv' -exec awk -v a="$na" -v b="$nb" '
FNR == a {print "==>", FILENAME, "<=="}
a <= FNR && FNR <= b
' {} +
コンテンツに関係なく、各ファイルのファイル名を印刷したい場合は、GNU awkが便利です。
find . -name '*.csv' -exec gawk -v a="$na" -v b="$nb" '
BEGINFILE {print "==>", FILENAME, "<=="}
a <= FNR && FNR <= b
' {} +
答え2
head
タイトルが好きで印刷すると、tail
そのうちの1人に印刷を依頼できます。 AからBまでの行を取得するには(1から計算)、最初にA行から始めるようにtail
指示し、+A
次に()ヘッドに最初の行B-A + 1を維持し、行1をヘッダー行として保持するように指示します。
tail -n "+$na" -v -- "$filename" | head -n $((nb - na + 2))
head
各ファイルの後に空の行がある find から呼び出されます ( or とほぼ同じですtail
。ここでコードは最後に空の行を追加します)。
find … -exec sh -c 'tail -n "+$1" -v -- "$0" | head -n $(($2 - $1 + 2)); echo' {} "$1" "$2" \;
答え3
find
byステートメントに印刷を実行させることができますprintf
。 inは-exec
+
もはや可能ではなく、ケースごとの呼び出しを使用する必要がありますawk
。
print-lines () {
na=$1
nb=$2
dir=$3
find "$dir" \( -name \*.org -o -name \*.texi \) \
-printf '==> %p <==\n\n' \
-exec awk -v a="$na" -v b="$nb" 'FNR >= a && FNR <= b' '{}' \; \
-printf '\n'
}
ソリューションを使用するよりもパフォーマンスがわずかに低下する可能性がありますawk
。
答え4
使用GNU sed-sオプションを使用して複数のファイルをsedに供給し、個別に処理します。
find "$dir" -type f \
\( -name "*.texi" -o -name "*.org" \) \
-exec sed -sne "
${na}{x;s/.*/==>/p;F;s//<==/p;x;}
$na,${nb}p
" {} +;
Pythonは階層をナビゲートするためにpathlibモジュールを結合し、ファイルを断片化するためにitertoolsを結合します。
python3 -c 'import pathlib, itertools, sys
na,nb,dir = sys.argv[1:]
p = pathlib.Path(dir)
for q in p.glob("**/*"):
if q.suffix in [".texi",".org"] and q.is_file():
with open(q.name) as f:
L = [l.rstrip("\n") for l in itertools.islice(f, int(na)-1, int(nb))]
if len(L) > 0:
print("==>",q.name,"<==")
print(*L,sep="\n")
' 2 4 .