我使用以下 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}' {} +
}
我有两个这样的文件
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
如果仅当文件至少有$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
,您可以让其中之一打印它。要获取从 A 到 B 的行(从 1 开始计数),首先告诉从tail
A 行开始 ( +A
),然后告诉 head 保留前 B-A+1 行,再加上 1 行作为标题行。
tail -n "+$na" -v -- "$filename" | head -n $((nb - na + 2))
从 find 调用,每个文件后面有一个空行(几乎与head
或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 .