印刷行の前にファイル名を印刷する

印刷行の前にファイル名を印刷する

ファイルの特定の行範囲を印刷するには、次の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

findbyステートメントに印刷を実行させることができます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 .

関連情報