标题应该是:Remove all lines between two similar patterns, including the line of the starting pattern. if another specific pattern in between is not matched
。我把它写得更短,因为它对于其他在谷歌上搜索答案的人来说更容易阅读。
关于问题:我有一个特定计算机的可上市股票和不可上市股票的列表。我想创建一个包含可列出共享的所有计算机的列表,并删除其不可读的共享。但我遇到了两个问题。首先,正确删除两个相似图案之间的所有线条。其次,如果发现特定模式,如何不删除两个相似单词之间的行。
我的意见是
Shares for DED-SHD-ED-5:
[--- Unreadable Shares ---]
ADMIN$
C$
E$
H$
IPC$
Shares for DED-SHD-ED-6:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
print$
Shares for DED-SHD-ED-7:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
backup backup2
Shares for DED-SHD-ED-8:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
Shares for DED-SHD-ED-9:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
VBRCatalog
[--- Listable Shares ---]
backup backup2
我设法使用以下命令删除所有不可读的共享awk '/Listable Shares/,/Shares for/' input.txt
,该命令的问题是DED-SHD-ED-8
没有Listable Shares
。它会剥离下面的计算机,我将看到atDED-SHD-ED-9
的可上市股票DED-SHD-ED-9
DED-SHD-ED-8
请参阅下面的输出(我知道列表中第一台计算机的名称丢失,但这对我来说不是问题)
[--- Listable Shares ---]
print$
Shares for DED-SHD-ED-7:
[--- Listable Shares ---]
backup backup2
Shares for DED-SHD-ED-8:
[--- Listable Shares ---]
backup backup2
为了解决这个问题,我的想法是在运行之前剥离所有没有可列表共享的计算机awk '/Listable Shares/,/Shares for/' input.txt
。起初,我尝试删除“Shares for”和“Shares for”之间的所有行。我在论坛上环顾四周,试图做出更简单的答案,并避免使用复杂的答案,因为它们目前超出了我的理解范围。例如,我使用了这个命令sed '/^Shares for/,/^Shares for/{//!d;};' input.txt
,sed '/Shares for/,/:/{//!d;};' input2.txt
在这里它删除了计算机之间的一半线路。
输出
Shares for DED-SHD-ED-5:
Shares for DED-SHD-ED-6:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
print$
Shares for DED-SHD-ED-7:
Shares for DED-SHD-ED-8:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
为什么它只删除一半计算机的数据?我不明白为什么
我的下一个想法是在命令中添加排除,如果模式Listable
在这些行中匹配,则不删除“Shares for”和“Shares for”之间的行。然后删除没有数据的计算机,如DED-SHD-ED-5
和DED-SHD-ED-7
。但也许这不是最好的方法。也许最好删除第一个模式的行,因为看不到模式“Listable”。
我希望得到一些帮助和见解,如何正确处理这一切。
预期输出:
Shares for DED-SHD-ED-6:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
print$
Shares for DED-SHD-ED-7:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
backup backup2
Shares for DED-SHD-ED-9:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
VBRCatalog
[--- Listable Shares ---]
backup backup2
答案1
这对你有用吗? shares
是我为您的示例输入选择的文件名。
sed -e 'tD' -e '$!N;/.\nShares/s/\n/&&/;:D' -e 'P;D' shares | awk 'BEGIN{RS="\n\n";FS="\n"}/Listable/'
Shares for DED-SHD-ED-6:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
print$
Shares for DED-SHD-ED-7:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
backup backup2
Shares for DED-SHD-ED-9:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
VBRCatalog
[--- Listable Shares ---]
backup backup2
如果还没有换行符,基本上sed
会在之前插入换行符Shares
- 这样我们就可以使用换行符RS="\n\n"
作为awk
.那么问题就很简单了:只打印包含该词的记录Listable
。
答案2
理解:
Shares
如果该块包含字符串,则打印该块Listable Shares
一旦您加入awk
其中,通常就可以消除对sed
.
一个(详细的)awk
想法:
$ cat shares.awk
NF == 0 { next } # skip blank lines
$1 == "Shares" { if (print_block) # if 1st field is "Shares"; if flag is set (==1) then ...
print block # print the previous block
print_block = 0 # clear the flag
block = $0 # initialize a new block
next # skip to next input line
}
/Listable Shares/ { print_block = 1 } # if line contains "Listable Shares" then set flag
{ block = block ORS $0 } # append current line to end of block
END { if (print_block) # flush last block to stdout?
print block
}
进行试驾:
$ awk -f shares.awk input.txt
Shares for DED-SHD-ED-6:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
print$
Shares for DED-SHD-ED-7:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
backup backup2
Shares for DED-SHD-ED-9:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
VBRCatalog
[--- Listable Shares ---]
backup backup2
答案3
使用乐(以前称为 Perl_6)
~$ raku -e '.put for slurp.comb(/^^Shares .*? <?before ^^Shares | $ >/).grep(/Listable/);' file
#OR:
~$ raku -e '.put for lines.join("\n").comb(/^^Shares .*? <?before ^^Shares | $ >/).grep(/Listable/);' file
Raku 是 Perl 家族的一种编程语言。在一个可能被认为是split
正则表达式模式上破坏性设置的相反操作中,Raku 提供了comb
允许您选择您选择的元素的例程。上面,通过.comb(/^^Shares .*? <?before ^^Shares | $ >/)
选择具有以下内容的记录将输入文件分为多个记录:
^^Shares
行首文本“共享”,.*?
非贪婪任意数量的字符,<?before ^^Shares | $ >
正向前瞻,表示在看到?before
下一个^^Shares
记录模式时或$
在文件本身的末尾之前/末尾停止该模式。
在链中的第二个操作中,grep
用于仅返回那些包含Listable
块的记录。
输入示例:
Shares for DED-SHD-ED-5:
[--- Unreadable Shares ---]
ADMIN$
C$
E$
H$
IPC$
Shares for DED-SHD-ED-6:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
print$
Shares for DED-SHD-ED-7:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
backup backup2
Shares for DED-SHD-ED-8:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
Shares for DED-SHD-ED-9:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
VBRCatalog
[--- Listable Shares ---]
backup backup2
示例输出:
Shares for DED-SHD-ED-6:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
print$
Shares for DED-SHD-ED-7:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
[--- Listable Shares ---]
backup backup2
Shares for DED-SHD-ED-9:
[--- Unreadable Shares ---]
ADMIN$
C$
IPC$
VBRCatalog
[--- Listable Shares ---]
backup backup2
注意:查看语言内部如何表示数据通常很有启发性,因此这里是输出后 comb
ing 到单独的记录中,但是前 grep
ping 所需的块:
~$ raku -e '.raku.put for slurp.comb(/^^Shares .*? <?before ^^Shares | $ >/);' file
"Shares for DED-SHD-ED-5:\n [--- Unreadable Shares ---]\n ADMIN\$\n C\$\n E\$\n H\$\n IPC\$\n\n"
"Shares for DED-SHD-ED-6:\n [--- Unreadable Shares ---]\n ADMIN\$\n C\$\n IPC\$\n [--- Listable Shares ---]\n print\$\n"
"Shares for DED-SHD-ED-7:\n [--- Unreadable Shares ---]\n ADMIN\$\n C\$\n IPC\$\n [--- Listable Shares ---]\n backup backup2\n"
"Shares for DED-SHD-ED-8:\n [--- Unreadable Shares ---]\n ADMIN\$\n C\$\n IPC\$\n\n"
"Shares for DED-SHD-ED-9:\n [--- Unreadable Shares ---]\n ADMIN\$\n C\$\n IPC\$\n VBRCatalog\n [--- Listable Shares ---]\n backup backup2\n\n"
https://docs.raku.org/language/operators#Operators
https://docs.raku.org/routine/comb
https://docs.raku.org/routine/grep
https://raku.org