我有一个具有以下结构的文件:
4168 Targus
1010 Wireless Compact Laser Mouse
4242 USB Design by Example
4201 Buttons and Lights HID device
4220 Echo 1 Camera
4255 GoPro
1000 9FF2 [Digital Photo Display]
2000 HD2-14 [Hero 2 Camera]
4317 Broadcom Corp.
0700 U.S. Robotics USR5426 802.11g Adapter
0701 U.S. Robotics USR5425 Wireless MAXg Adapter
0711 Belkin F5D7051 v3000 802.11g
0720 Dynex DX-BUSB
0721 Dynex DX-EBUSB
4348 WinChipHead
5523 USB->RS 232 adapter with Prolific PL 2303 chipset
5537 13.56Mhz RFID Card Reader and Writer
5584 CH34x printer adapter cable
4572 Shuttle, Inc.
4572 Shuttle PN31 Remote
这里每个部分都由非空白字符分隔。我不知道文件中每个部分的开头字母及其行号。
在 bash 或 python 3 中,读取两个部分之间的行的方式是什么?
在上面的示例中,第一部分将是第 4168 行,直到下一行之前的一行(以非空白字符开头)。所以第一部分有一行
1010 Wireless Compact Laser Mouse
第二部分包括:
4201 Buttons and Lights HID device
4220 Echo 1 Camera
部分选择是通过给定的输入完成的。例如如果4242输入,则所需阅读的部分将是:
4201 Buttons and Lights HID device
4220 Echo 1 Camera
请注意,我不知道行号4242。
答案1
num=4242
sed -n '
/^'"$num"'\b/,/^[^[:blank:]]/{
/^[[:blank:]]/ {s/^[[:blank:]]*//;p}
}' data_file
在 GNU 4.7 中测试sed
。
变量展开后,4242
出现在sed
代码中。定义从位于最开始并且是完整单词(例如,区分)的行到没有前导空白(制表符或空格)的第一行/^4242\b/,/^[^[:blank:]]/
的范围。4242
42421
在该范围内,以空白 ( /^[[:blank:]]/
) 开头的行已删除前导空白 ( s/^[[:blank:]]*//
) 并打印 ( p
)。
笔记:
- 如果有两个或多个部分被识别,
4242
那么您将从所有这些部分获得行,而没有任何指示这些行来自不同的部分。 - 在子 shell ( ) 中运行代码以避免在当前 shell 中
(num=…; sed …)
设置(或更改)变量。num
答案2
强制awk
解决方案:
awk -v sect="4242" '$0~/^[[:digit:]]/ {if ($1==sect) {p=1;next} else p=0} p' input.txt
- 该部分通过语句指定为
awk
变量。sect
-v
- 如果找到立即以数字开头的行,则将其视为节开始。如果节号与所需的节匹配,我们将一个标志
p
(用于“打印”)设置为1
,但跳过处理到下一行(因此我们不打印节的开头)。如果节号不匹配,我们将标志设置为0
。 p
仅当is时才打印当前行1
。
如果要从输出中去除前导空格,请按如下方式修改程序:
awk -v ... '$0~/^[[:digit:]]/ {if ($1==sect) {p=1;next} else p=0}
p{sub(/^[[:space:]]+/,""); print}' input.txt
答案3
我提出这个解决方案,假设@
文件内容中没有 :
$ sed -e 's/^\([0-9]\)/@\1/' -n -e '/@4317/,/@/p' file | sed -e '/^@/d' -e 's/^[[:blank:]]*//'
0700 U.S. Robotics USR5426 802.11g Adapter
0701 U.S. Robotics USR5425 Wireless MAXg Adapter
0711 Belkin F5D7051 v3000 802.11g
0720 Dynex DX-BUSB
0721 Dynex DX-EBUSB
's/^\([0-9]\)/@\1/'
替换 的行起始编号@
。'/@4317/,/@/p'
选择两个 之间的内容@
(给定标识符号)。sed -e '/^@/d' -e 's/^[[:blank:]]*//'
删除以@
和 开头的空白行。