Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在子文件夹中搜索多个文件并仅打印数值_Bash_Awk_Sed_Grep_Cut - Fatal编程技术网

Bash 在子文件夹中搜索多个文件并仅打印数值

Bash 在子文件夹中搜索多个文件并仅打印数值,bash,awk,sed,grep,cut,Bash,Awk,Sed,Grep,Cut,我对使用两种模式在子文件夹中搜索多个文件并仅打印数值的联机操作有疑问 例如: 当前目录:$HOME/work/A/(运行脚本的位置) 包含数据的子文件夹:$HOME/work/A/trial1、trial2、trial3.. 输入(每个数据文件):例如trial1/trial1.out [text] .. cutoff = 100 .. [text] .. ! total energy= -23.4387 Ry .. 需要输出:/A/totalenergy.txt 100 -23.43

我对使用两种模式在子文件夹中搜索多个文件并仅打印数值的联机操作有疑问

例如:

当前目录:
$HOME/work/A/
(运行脚本的位置)

包含数据的子文件夹:
$HOME/work/A/trial1、trial2、trial3..

输入(每个数据文件):例如
trial1/trial1.out

[text]
..
cutoff = 100
..
[text] 
..
! total energy= -23.4387 Ry
.. 
需要输出:
/A/totalenergy.txt

100   -23.4387
110   -23.2523
120   -24.0134
...
我最初计划的是使用“grep”搜索每个文件并匹配模式“cutoff=”和“!”找到所需的两行,只打印截止数字和能量数字

然而,到目前为止,我所能做的只是搜索1个模式'!总能量”(更重要),并使用
grep | tr | cut>file
仅获取能量

grep -e "\!" */*.out | tr -s ' ' | cut -f5 -d' ' >totalenergy.txt
基本上,我用grep表示“!”,在所有子文件夹中搜索*.out,修剪多个空格,并仅保留数字字段

包含“”的行!使用grep后的“总能量”如下所示

60/C.scf_60.out:!    total energy              =     -22.78085574 Ry
因此,如果我能从这行中找出第一个数字,再加上我所拥有的,我也能实现我的目标:

60  -22.78085574
我正试图用一行命令来实现这一点

谢谢

sed -rn -e 's/cutoff[ =]+([0-9]+)/\1/p' -e 's/.*total energy[= ]+([0-9.-]+).*/\1:/p' */*.out | tr '\n:' ' \n'

说明: 需要与我使用的sintax匹配。特别是
([0-9.-]+)
->我不需要跳出括号,我可以毫无问题地过滤
-

-n # short option of --quiet or --silent
它禁用模式打印,除非我们明确要求这样做(使用标志
p

用于组合多个命令

模式与替代 我只是将需要的值保存在
\1

请注意,我在与总能量匹配的值之后附加了一个
字符。正如我所说的,它是为了帮助我用
tr
分离寄存器

塞德旗 我已使用
p
打印图案,因为我已使用
-n
禁用打印。需要丢弃所有不匹配的行


由于
sed
在不同的行中输出每个值,我使用了一个标志(
)来知道在哪里写换行符(
\n

字符替换 正在将字符从集合1(
'\n:'
)转换为集合2中的字符(
'\n'
)。翻译是将SET1中的每个字符替换为SET2中相同位置的每个字符:

# \n  ->  " " (space)
# :   ->  \n
注意:您可能希望再次使用管道(
|tr-s'
)来清理输出


另一种格式化输出的方法 打印结果更严格的方法是再次
sed
,以便输出完全符合您的要求:

sed -rn -e 's/cutoff[ =]+([0-9]+)/\1/p' -e 's/.*total energy[= ]+([0-9.-]+).*/\1:/p' */*.out | tr '\n' ' ' | sed -r "s/([^:]+):[ ]*/\1\n/g"
请注意,第一个
|
命令与上面的命令完全相同

tr '\n' ' '
它只是用空格替换换行符

sed -r "s/([^:]+):[ ]*/\1\n/g"

它将字符串保存到
,然后打印它,后面是一个换行符
egrep'pat1 | pat2'文件
可能会给您一些想法。祝你好运,谢谢。egrep是gnu独有的吗?不,
egrep
可以追溯到20世纪90年代的Unix系统(至少);-)。如果您使用的是基于
gnu
的系统,那么您可以执行
grep-E'pat1 | pat2'文件
(我非常确定)。在这两种情况下,
[Ee]
都指“E”扩展的正则表达式支持。而
'pat1 | pat2'
是扩展reg expression的一种zillon形式。祝你好运。非常感谢你,雪勒!正如您和jaba10所建议的,需要两个命令来完成我想要的任务。我刚刚添加了一种方法来再次执行
sed
。我希望它能帮助你。
's/../../p'
tr '\n:' ' \n'
# \n  ->  " " (space)
# :   ->  \n
sed -rn -e 's/cutoff[ =]+([0-9]+)/\1/p' -e 's/.*total energy[= ]+([0-9.-]+).*/\1:/p' */*.out | tr '\n' ' ' | sed -r "s/([^:]+):[ ]*/\1\n/g"
tr '\n' ' '
sed -r "s/([^:]+):[ ]*/\1\n/g"