我想要一种从参考管理器 Zotero 导出笔记的简单方法。我首先选择多个笔记并将它们拖到一个空白文本文件中。我还希望实现笔记的“原子性”,因此我需要将生成的文本文件拆分,其中包含由破折号分隔的部分中的各个笔记。然后我想使用我给每个注释的标题来命名新文件,即:用每个部分的第一行重命名。我想将这些新文件保存为降价文件。
我编写的脚本是由网络上的贡献者对这些功能中的每一个的建议组成的。在与与我有类似用例的同事分享之前,我试图确保我正确理解了脚本中的命令。我对“head”命令中“$f”周围需要引号的理解(通过阅读 Gilles 对另一个问题的回答 - 请参见下面的参考链接)似乎不正确。我尝试了不带引号的脚本并得到了相同的结果。是否真的不需要双引号,因为“$f”出现在作业的右侧?它们只是因为默认情况下双引号比记住不需要它们更容易吗?任何进一步的解释将不胜感激。
Notes_test.txt 中的输入文件示例如下
This is note 1
It has some notes
--------------------------------------------------
This is note 2
It has some more notes
它的输出应该是两个文件:
This is note 1.md
This is note 2.md
这是我在命令行上使用的脚本:
csplit Notes_test.txt -f_ -z -b'%03d.md' /--------------------------------------------------/1 {*} && sed -i '/./,$!d' *.md && for f in *.md
do
f1=$(head -n1 "$f")
mv -n "$f" "$f1.md"
done
这是我迄今为止对命令的理解:
-fPREFIX 使用 PREFIX 作为输出文件名前缀。在这种情况下,指定了一个下划线:我看到的“_”只是一个占位符。
-z 禁止生成零长度输出文件。我认为这是必要的,因为否则 csplit 将在每次运行结束时通过拆分原始文件生成一个空文件。
-bSuffix 使用 SUFFIX 作为输出文件名的后缀。在这种情况下:“md”
%03d 将 3 位数字作为文件名的占位符。在 FelixJN 的建议下,我在 3 之前添加了零。
/---------------------------------------------------- -/1 指定拆分的分隔符,拆分在“-”行下方 2 行(计数从 0 开始)。
{*} 告诉 bash 运行拆分直到文件结束。正如 Felix 指出的那样,“{n}”是要执行的拆分数。在这种情况下,“*”表示尽可能多地做。
&& 表示在上一条命令完成的情况下执行下面的命令
sed -i 指示 sed 对具有特定后缀的文件进行操作 '/./,$!d' 表示“删除文件头的空白行” 再次感谢 Felix 解释这是指定 sed 工作的范围: 一个 ”。” 表示任何字符,因此它指定文档中出现的第一个字符。由于空行没有任何字符,我们需要应用否定“!” 定义范围后。范围由模式 /"start"/,/"end"/ 定义,以在字符串 "start" 和 "end" 之间应用命令。$ 指的是最后一行,因此范围是文档中的所有非空行。应用否定使用“!” 意思是“NOT”,即告诉 sed 选择与前一个范围相反的值。在这种情况下,第一行之前的所有行都带有任何字符。"d" 然后删除这些行。
*.md 表示“任何名称后缀为 .md”
f1=$(head -n1 "$f") 表示:将 f1 定义为文件的第一行(“head”表示“第一行”)。这是通过使用变量符号“$”来定义“f1”来完成的,它将作为新文件名(减去后缀)的占位符(在脚本的下一行)。“head”是一个 bash 命令,通常输出每个文件的前 10 行: head [OPTION]... [FILE]... 选项 -n1 指定仅输出一行。这里,“$f”不是指定一个特定的文件,而是指定“所有文件”。需要在 "$f" 周围加上引号,以便忽略空格(否则 $f 使用空格作为字段分隔符并进一步拆分文件 - 请参阅下面的参考链接)。
mv -n "$f" "$f1.md" 意思是:将每个文件重命名为 "f1.md"
bash 命令“mv”采用选项和参数: mv [OPTION]... [-T] SOURCE DEST 即:“将 SOURCE 重命名为 DEST。” -n 选项代表 --no-clobber “不要覆盖现有文件”。我认为这是以防万一有文件(注释)具有相同的第一行。
请参阅https://www.tutorialspoint.com/unix_commands/csplit.htm和 coreutils 以了解https://www.gnu.org/software/coreutils/manual/coreutils.pdf 和https://www .howtoforge.com/linux-csplit-command/ Q2.如何使用正则表达式拆分文件?为什么我的 shell 脚本会因空格或其他特殊字符而窒息 ?什么时候需要双引号?
由于我认为您的理解没有任何问题,因此我将重点介绍该
sed
部分。范围
sed
可以在一个范围内执行命令,例如用从第 11 行到第 20 行替换(s
替换)一个A
(即一行中的第一个)B
看起来像:范围也可以通过模式匹配来定义,以在字符串和
/start/,/end/
之间应用命令。start
end
在您的情况下,我们有
/./,$
.A
.
表示任何字符,空行没有任何字符,所以它只适用于非空行。$
只是指最后一行,所以我们会对整个文档执行此操作,但会跳过开头的空行。现在
!
开始起作用,这意味着NOT,即选择与先前范围相反的范围。在这种情况下,第一行之前的所有行都带有一个字符。d
然后删除这些行。中的另一条评论
'{*}'
。是要执行的拆分数,星号表示尽可能多。你也只能分裂5次。csplit
'{n}'
而不是
%3d
,我建议使用%03d
零填充的三位数字,它使排序更容易。