它可以将 head、sed 和 regex 一起工作到一个 bash 脚本中吗?
Can it work together head, sed and regex into one bash script?
我 MyInitialTextFile.txt 具有以下特征:<p><nsup></nsup> <b>Abc 1:2<sup>varied text
.
- 每一行都以此开头:
<p><nsup></nsup> <b>
- 后面跟着这样的表达式:Abc 1:2 或 2Ab 1:2
- 始终后跟:
<sup>
- 随后是各种文字。
<p><nsup></nsup> <b>
Abc 1:2<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:2<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:3<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:4<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:4<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:4<sup>
各种文字
我需要:
- Select 来自 MyInitialTextFile.txt 的第一行(如果它们的开头相同)。在我的例子中,前两行。然后把这两行转成一个TransitionalTextFile.txt
为此,我在 bash:
中使用了 head
head -n 2 MyInitialTextFile.txt > TransitionalTextFile.txt
- 我将在其中手动应用两个正则表达式的序列。
对于我使用的正则表达式:
Find1: (\n) #即查找换行符(键盘输入)
Replace1: " " #即替换为5个空格
Find2: (.*) #即select整个字符串
Replace2: $1\n #即替换为所有selected(整个字符串),最后加一个换行。
将TransitionalTextFile.txt的内容转移到与第一个字符串Abc中找到的同名的新文本文件的末尾1:2.
为此,我使用了:
head -n 1 TransitionalTextFile.txt >> 'Abc 1:2.txt'
这将始终是 -n 1 因为在正则表达式步骤之后,所有文本都变成一个条目,即使最初有两个字符串 selected。
从MyInitialTextFile.txt中删除我转移的行数,对我来说有两行。
为此,我在 bash:
中使用了 sed
sed -i '1,2d' MyInitialTextFile.txt
然后该过程继续下一行:
<p><nsup></nsup> <b>
Abc 1:3<sup>
各种文字
我手动完成了以上四个步骤,但我的问题是如何将所有这四个步骤整合到一个脚本中。也就是说,select 来自初始文件的字符串,并通过正则表达式将它们传输到另一个文件,我删除了它们之间的换行符,并在它们的末尾添加了一个换行符,这样它看起来像这样:
<p><nsup></nsup> <b>
Abc 1:2<sup>
各种文字 <p><nsup></nsup> <b>
Abc 1:2<sup>
各种文字
最后我必须从我的初始文件中删除这两个字符串。
如果能将这四个步骤整合到一个脚本中,我将不胜感激。
谢谢。
像这样(为团队拿一个:)?使用 awk(注意: 它创建类似 Abc 1:2
或 <b>
和 <sup>
之间的任何文件):
$ awk '
BEGIN {
FS="<sup>" # split at this delimiter
}
{
if(==p) { # if first part equals first part of previous split
b=b " " [=10=] # append to the output buffer
}
else { # if first part differs, do stuff
if(NR>1) { # first line needs not printing
print b >> t[n]
# close t[n] # uncomment if if needed
}
n=split(,t,/<b>/) # get the changing part
b=[=10=] # reset buffer
}
p= # create previous to compare on next round
}
END {
print b >> t[n] # flush the rest of the buffer
}' file
cat Abc\ 1\:2
的输出:
<p><nsup></nsup> <b>Abc 1:2<sup>varied text <p><nsup></nsup> <b>Abc 1:2<sup>varied text
根据使用的 awk 风格,如果您从文件描述符开始 运行,请在 print >>
之后添加一个 close(t[n])
。
在 sed
中实现 head
很容易,因此通常没有必要将两者结合起来。但是,您的问题似乎更适合 Awk,它比 sed
.
相当隐晦和简洁的低级语言更易于阅读和编写。
猜测一下您的预期输出应该是什么样子,试试这个。
awk '/^<p><nsup><\/nsup> <b>/ {
str = substr([=10=], 21); split(str, n, /<sup>/);
if (n[1] != id) {
if (d) { printf "\n" >d; close (d) }
d = n[1] ".txt"
id = n[1]
sep = ""
}
printf "%s%s", sep, [=10=] >d
sep = " "
}
END { if (d) printf "\n" >d }' MyInitialTextFile.txt
这会提取 <b>
和 <sup>
之间的字符串,并将每一行写入以该字符串命名的文件,用五个空格替换换行符。
我 MyInitialTextFile.txt 具有以下特征:<p><nsup></nsup> <b>Abc 1:2<sup>varied text
.
- 每一行都以此开头:
<p><nsup></nsup> <b>
- 后面跟着这样的表达式:Abc 1:2 或 2Ab 1:2
- 始终后跟:
<sup>
- 随后是各种文字。
<p><nsup></nsup> <b>
Abc 1:2<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:2<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:3<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:4<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:4<sup>
各种文字
<p><nsup></nsup> <b>
Abc 1:4<sup>
各种文字
我需要:
- Select 来自 MyInitialTextFile.txt 的第一行(如果它们的开头相同)。在我的例子中,前两行。然后把这两行转成一个TransitionalTextFile.txt 为此,我在 bash: 中使用了 head
head -n 2 MyInitialTextFile.txt > TransitionalTextFile.txt
- 我将在其中手动应用两个正则表达式的序列。 对于我使用的正则表达式:
Find1: (\n) #即查找换行符(键盘输入)
Replace1: " " #即替换为5个空格
Find2: (.*) #即select整个字符串
Replace2: $1\n #即替换为所有selected(整个字符串),最后加一个换行。
将TransitionalTextFile.txt的内容转移到与第一个字符串Abc中找到的同名的新文本文件的末尾1:2. 为此,我使用了:
head -n 1 TransitionalTextFile.txt >> 'Abc 1:2.txt'
这将始终是 -n 1 因为在正则表达式步骤之后,所有文本都变成一个条目,即使最初有两个字符串 selected。
从MyInitialTextFile.txt中删除我转移的行数,对我来说有两行。 为此,我在 bash:
中使用了 sedsed -i '1,2d' MyInitialTextFile.txt
然后该过程继续下一行:
<p><nsup></nsup> <b>
Abc 1:3<sup>
各种文字
我手动完成了以上四个步骤,但我的问题是如何将所有这四个步骤整合到一个脚本中。也就是说,select 来自初始文件的字符串,并通过正则表达式将它们传输到另一个文件,我删除了它们之间的换行符,并在它们的末尾添加了一个换行符,这样它看起来像这样:
<p><nsup></nsup> <b>
Abc 1:2<sup>
各种文字 <p><nsup></nsup> <b>
Abc 1:2<sup>
各种文字
最后我必须从我的初始文件中删除这两个字符串。 如果能将这四个步骤整合到一个脚本中,我将不胜感激。 谢谢。
像这样(为团队拿一个:)?使用 awk(注意: 它创建类似 Abc 1:2
或 <b>
和 <sup>
之间的任何文件):
$ awk '
BEGIN {
FS="<sup>" # split at this delimiter
}
{
if(==p) { # if first part equals first part of previous split
b=b " " [=10=] # append to the output buffer
}
else { # if first part differs, do stuff
if(NR>1) { # first line needs not printing
print b >> t[n]
# close t[n] # uncomment if if needed
}
n=split(,t,/<b>/) # get the changing part
b=[=10=] # reset buffer
}
p= # create previous to compare on next round
}
END {
print b >> t[n] # flush the rest of the buffer
}' file
cat Abc\ 1\:2
的输出:
<p><nsup></nsup> <b>Abc 1:2<sup>varied text <p><nsup></nsup> <b>Abc 1:2<sup>varied text
根据使用的 awk 风格,如果您从文件描述符开始 运行,请在 print >>
之后添加一个 close(t[n])
。
在 sed
中实现 head
很容易,因此通常没有必要将两者结合起来。但是,您的问题似乎更适合 Awk,它比 sed
.
猜测一下您的预期输出应该是什么样子,试试这个。
awk '/^<p><nsup><\/nsup> <b>/ {
str = substr([=10=], 21); split(str, n, /<sup>/);
if (n[1] != id) {
if (d) { printf "\n" >d; close (d) }
d = n[1] ".txt"
id = n[1]
sep = ""
}
printf "%s%s", sep, [=10=] >d
sep = " "
}
END { if (d) printf "\n" >d }' MyInitialTextFile.txt
这会提取 <b>
和 <sup>
之间的字符串,并将每一行写入以该字符串命名的文件,用五个空格替换换行符。