JoV*_*oVe 4 shell grep sed awk text-processing
我有一个像下面这样的文件:
blablabla
blablabla
***
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
blablabla
blablabla
Run Code Online (Sandbox Code Playgroud)
我想用thingsIwantToRead
. 当我不得不处理这样的问题时,我是这样使用AWK的:
awk 'BEGIN{ FS="Separator above the paragraph"; RS="" } {print $2}' $file.txt | awk 'BEGIN{ FS="separator below the paragraph"; RS="" } {print $1}'
Run Code Online (Sandbox Code Playgroud)
它奏效了。
在这种情况下,我尝试放置FS="***"
, "\*{3}"
, "\*\*"
(它不起作用,因为 AWK 将其视为普通星号),"\\*\\*"
或者我能想到的任何正则表达式,但它不起作用(它不打印任何内容)。
你知道为什么吗?
如果没有,你知道另一种方法来处理我的问题吗?
在我要解析的文件的摘录下方:
13.2000000000 , 3*0.00000000000 , 11.6500000000 , 3*0.00000000000 , 17.8800000000
Blablabla
SATELLITE EPHEMERIS
===================
Output frame: Mean of J2000
Epoch A E I RA AofP TA Flight Ang
*****************************************************************************************************************
2012/10/01 00:00:00.000 6998.239 0.001233 97.95558 77.41733 89.98551 290.75808 359.93398
2012/10/01 00:05:00.000 6993.163 0.001168 97.95869 77.41920 124.72698 274.57362 359.93327
2012/10/01 00:10:00.000 6987.347 0.001004 97.96219 77.42327 170.94020 246.92395 359.94706
2012/10/01 00:15:00.000 6983.173 0.000893 97.96468 77.42930 224.76158 211.67042 359.97311
<np>
----------------
Predicted Orbit:
----------------
Blablabla
Run Code Online (Sandbox Code Playgroud)
我想提取:
2012/10/01 00:00:00.000 6998.239 0.001233 97.95558 77.41733 89.98551 290.75808 359.93398
2012/10/01 00:05:00.000 6993.163 0.001168 97.95869 77.41920 124.72698 274.57362 359.93327
2012/10/01 00:10:00.000 6987.347 0.001004 97.96219 77.42327 170.94020 246.92395 359.94706
2012/10/01 00:15:00.000 6983.173 0.000893 97.96468 77.42930 224.76158 211.67042 359.97311
Run Code Online (Sandbox Code Playgroud)
我试图用来获取 * 行后的数字的命令:
`awk 'BEGIN{ FS="\\*{2,}"; RS="" } {print $2}' file | awk 'BEGIN{ FS="<np>"; RS="" } {print $1}'`
Run Code Online (Sandbox Code Playgroud)
告诉 awk 在两个分隔符之间打印。具体来说:
awk '/\*{4,}/,/<np>/' file
Run Code Online (Sandbox Code Playgroud)
这也将打印包含分隔符的行,因此您可以使用以下命令删除它们:
awk '/\*{4,}/,/<np>/' file | tail -n +2 | head -n -1
Run Code Online (Sandbox Code Playgroud)
或者,如果一行与第一个分隔符匹配,则可以将变量设置为 true,当它与第二个分隔符匹配时设置为 false,并且仅在为 true 时才打印:
awk '/\*{4,}/{a=1; next}/<np>/{a=0}(a==1){print}' file
Run Code Online (Sandbox Code Playgroud)
a
如果当前行匹配 4 个或更多*
,则上面的命令将设置为 1,并且也会跳到该next
行。这意味着***
永远不会打印该行。
这是对最初的、被误解的问题版本的回答。我把它留在这里是因为它在稍微不同的情况下很有用。
首先,你不想要FS
(字段分隔符),你想要RS
(记录分隔符)。然后,要传递一个文字*
,您需要对其进行两次转义。一次转义 the *
,一次转义反斜杠(否则,awk 将尝试以与\r
or相同的方式匹配它\t
)。然后,打印第二个“行”:
$ awk -vRS='\\*\\*\\*' 'NR==2' file
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
Run Code Online (Sandbox Code Playgroud)
为避免输出周围出现空行,请使用:
$ awk -vRS='\n\\*\\*\\*\n' 'NR==2' file
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
Run Code Online (Sandbox Code Playgroud)
请注意,这假定***
在每个段落之后,而不仅仅是在您显示的第一个之后。
除了@terdon 的回答之外,使用 awk(和 sed),您还可以使用范围模式:
awk '/sep1/,/sep2/{print}' file
Run Code Online (Sandbox Code Playgroud)
或者
sed -n '/sep1/,/sep2/p' file
Run Code Online (Sandbox Code Playgroud)
将打印所有内容(包括)sep1
和sep2
. 那是:
~$ awk '/sep1/,/sep2/{print}' file
sep1
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
sep2
Run Code Online (Sandbox Code Playgroud)
在你的情况下:
~$ awk '/\*\*\*/,/^$/{print}' file
***
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
Run Code Online (Sandbox Code Playgroud)
然后您可能想要删除第一行和最后一行。
例如:
~$ sed -n '/\*\*\*/,/^$/p' file | sed '1d;$d'
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
Run Code Online (Sandbox Code Playgroud)
或者
~$ awk '/\*\*\*/,/^$/{print}' file | awk 'NR>1&&!/^$/ {print}'
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
Run Code Online (Sandbox Code Playgroud)
如果你的段落不是太长。
归档时间: |
|
查看次数: |
6097 次 |
最近记录: |