如何使用 awk、bash 或 ruby​​ 迭代文件?

如何使用 awk、bash 或 ruby​​ 迭代文件?

我的机器上有三个 Markdown 文件:

$ ls | grep md
bar.md
baz.md
foo.md

每个文件都有给定的内容:

$ cat *md
i am bar
i am baz
i am foo

举个例子,我想“循环遍历与模式匹配的所有文件*.md并打印模式:file_name: file_contents”。

我最喜欢使用 ruby​​。但我想练习一下我的bash for 循环并也发展我的awk技能。

Ruby 对我来说是最简单的:

#!/usr/bin/env ruby
# iterate over all markdown files in current directory

Dir.glob('*.md').each do |some_file|
  puts "#{some_file}: #{File.read(some_file)}"
end

输出:

$ ./iterate_over_files.rb
bar.md: i am bar
baz.md: i am baz
foo.md: i am foo

并按照链接bash 资源我创建了以下 for 循环:

#!/usr/bin/env bash
# iterate over all markdown files in current directory

for some_file in *.md
do
  echo $some_file: `cat $some_file`
done

给出相同的输出:

$ diff <(./iterate_over_files.sh) <(./iterate_over_files.rb) # no difference

我通过观看演示得知布赖恩·科纳汉并从审查他的幻灯片这是使用 awk 的好机会,因为它遵循以下模式:

for each file
  for each input line 
    for each pattern
      if the pattern matches input line
        do the action
  • 如何使用 awk 来利用此模式并迭代所有 Markdown 文件并打印格式化结果?

答案1

怎么样,处理每个文件并使用 FILENAME 变量输出文件名。

$ awk '{print FILENAME":",$0}' *.md
bar.md: i am bar
baz.md: i am baz
foo.md: i am foo
$

或者这个,有点难看,但只需将 $0 设置为文件名,后跟文件内容。默认操作awk是打印 $0,所以这就是为什么它不需要print.

$ awk '$0=FILENAME": "$0' *.md
bar.md: i am bar
baz.md: i am baz
foo.md: i am foo
$

另一种方法。不使用 FILENAME,而是使用 ARGV 参数数组。

$ awk '$0=ARGV[++z]": "$0' *.md
bar.md: i am bar
baz.md: i am baz
foo.md: i am foo
$

答案2

根据bash手册,您应该使用$(< FILE)而不是$(cat FILE).但根本不需要使用命令替换:

for some_file in *.md
do
  echo -n "$some_file: "
  cat $some_file
done

由于您已经知道进程替换,您还可以执行以下操作:

for some_file in *.md
do
  cat <(echo -n "$some_file: ") $some_file
done

相关内容