我正在尝试创建一个 for 循环,该循环读取打印文件名、按字母顺序排列字段并添加 html 标签,最终创建一个如下所示的 html 文件
<h3 id= filename> file </h3>
<li> field2(field3)</li>
<li> field2(field3)</li>
<li> field2(field3)</li>...
<h3 id= filename> file </h3>
等等。
到目前为止我有这个:
for file in *.csv; do
awk 'FNR == 1{ print "<h3 id=" file ">" file "</h3>" }' | sort -t"," -k2 | awk -F "," '{print "<li>" $2 "(" $3 ")<\li>" }' > *.html
done
最后两个命令配合得很好,但第一个命令把它们搞乱了,我最终得到了一个空的 html 文件。我也不确定我是否为这种情况创建了正确的 for 循环。
答案1
您已经(为了可读性而稍微重新格式化):
for file in *.csv; do
awk 'FNR == 1{ print "<h3 id=" file ">" file "</h3>" }' |
sort -t"," -k2 |
awk -F "," '{print "<li>" $2 "(" $3 ")<\li>" }' > *.html
done
第一个
awk
命令没有任何意义。它既没有收到任何输入标准输入它也不接收文件列表作为参数:换句话说,它不处理任何内容。→ 我们需要向 awk 提供输入,如下所示:
awk '...awk script here...' "$file"
或者通过将其输入标准输入。
您正在尝试引用该
awk
变量file
。但没有这样的变量。当然有一个壳变量具有该名称,但awk
对此一无所知。→ 我们需要将
file
变量提供给awk
.我们可以做这样的事情:awk -v file="$file" ...
您尝试插入的方式
sort
之间两次awk
通话似乎很尴尬。→ 我们
sort
先调用,然后将输出提供给awk
您永远不会
<ul>...</ul>
在列表元素周围创建。→ 让我们确保将这些元素包含在我们的输出中。
您试图将输出重定向到
*.html
,但这不会达到您想要的效果。这将根据当前目录中存在的文件产生不同的行为。→ 我们应该根据输入文件名构造输出文件名。如果
something.csv
我们想要输出一个名为 的输入文件something.html
,我们可以这样写:"${file%.csv}.html"
该表达式
${file%.csv}
是一个 bash 表达式,它.csv
从变量的内容中删除file
。
看起来也许你想要类似的东西:
#!/bin/bash
for file in *.csv; do
sort -t"," -k2 "$file" |
awk -v file="$file" -F"," '
BEGIN {
printf "<h3 id=\"%s\">%s</h3>\n", file, file
printf "<ul>\n"
}
{
printf "<li>%s (%s)</li>\n", $2, $3
}
END {
printf "</ul>\n"
}
' > "${file%.csv}.html"
done
给定输入:
alice,8,alice,alice,alice
bob,6,bob,bob,bob
carol,7,carol,carol,carol
david,5,david,david,david
edith,4,edith,edith,edith
frank,3,frank,frank,frank
grace,2,grace,grace,grace
这会产生输出:
<h3 id="file1.csv">file1.csv</h3>
<ul>
<li>2 (grace)</li>
<li>3 (frank)</li>
<li>4 (edith)</li>
<li>5 (david)</li>
<li>6 (bob)</li>
<li>7 (carol)</li>
<li>8 (alice)</li>
</ul>
printf
(您可以将我在 awk 脚本中使用的 替换为print
,但我发现printf
更容易使用。)