最容易举一个例子。
bash-$ psql -c 'select relname, reltype from pg_catalog.pg_class limit 5;
relname | reltype
------------------------+---------
bme_reltag_02 | 0
bme_reltag_type1_type2 | 0
bme_reltag_10 | 0
bme_reltag_11 | 0
bme_reltag_cvalue3 | 0 ? what I care about
但是我真正感兴趣的是其中包含cvalue
的任何内容。无需手动修改每个查询(是的,我知道我可以做到),我可以egrep
关心自己的事情。
psql -c 'select relname, reltype from pg_catalog.pg_class limit 5;' | egrep 'cvalue'
但这会删除带有列标题的前两行。
bme_reltag_cvalue3 | 0
我知道我也可以这样做:
psql -c 'select relname, reltype from pg_catalog.pg_class limit 5;' | head -2 && psql -c 'select relname, reltype from pg_catalog.pg_class limit 5;' | egrep 'cvalue'
relname | reltype
------------------------+---------
bme_reltag_cvalue3 | 0
但是我真正想做的是以某种方式保留某些行的头部(或尾部),然后以另一种方式处理其余的行。
我在这里的特殊用例是重复任意psql
选择的内容,但是我很好奇该域中的bash功能。
我之前通过写入临时文件然后分多个步骤处理临时文件来完成此操作,但这不是我想要的。
答案 0 :(得分:3)
一个while读取循环和grep,如果可以的话。
#!/usr/bin/env bash
while IFS= read -r lines; do
[[ $lines == [12]* ]] && echo "${lines#*:}"
[[ $lines == *cvalue[0-9]* ]] && echo "${lines#*:}"
done < <(psql -c 'select relname, reltype from pg_catalog.pg_class limit 5;' | grep -n .)
如果没有grep
,则可以选择一个计数器来知道行号,这将是纯bash解决方案。
#!/usr/bin/env bash
counter=1
while IFS= read -r lines; do
[[ $counter == [12] ]] && echo "$lines"
[[ $lines == *cvalue[0-9]* ]] && echo "$lines"
((counter++))
done < <(psql -c 'select relname, reltype from pg_catalog.pg_class limit 5;')
如果bash4+
可用。
#!/usr/bin/env bash
mapfile -t files < <(psql -c 'select relname, reltype from pg_catalog.pg_class limit 5;')
printf '%s\n' "${files[0]}" "${files[1]}"
unset 'files[0]' 'files[1]'
for file in "${files[@]}"; do
[[ $file == *cvalue[0-9]* ]] && echo "$file"
done
默认情况下,内置read
会去除开头和结尾的空格,因此在这种情况下我们不希望这样做,因此我们使用IFS=
grep -n .
在行号上添加:
[12]
是一个非正则表达式的glob,表示1或2,并且*
的glob如果是该行的第一个字符,则将匹配。
*cvalue[0-9]*
将与cvalue
及其旁边的任意整数/数字匹配。
"${lines#*:}"
是参数扩展,剥离了前导:
<( )
被称为进程替换。
答案 1 :(得分:3)
$ psql -c ... | awk 'NR<3 || /cvalue/' file
答案 2 :(得分:2)
sed
可以使用其范围功能仅在第3行及以后的行上进行操作
sed '3,${/cvalue/!{d;};}'
$ cat ./psql
relname | reltype
------------------------+---------
bme_reltag_02 | 0
bme_reltag_type1_type2 | 0
bme_reltag_10 | 0
bme_reltag_11 | 0
bme_reltag_cvalue3 | 0
$ sed '3,${/cvalue/!{d;};}' ./psql
relname | reltype
------------------------+---------
bme_reltag_cvalue3 | 0
3,${...;}
:从第3行开始处理,直到文件$
结束/cvalue/!{d;}
:删除d
与(!
)正则表达式/cvalue/
不符的任何行答案 3 :(得分:0)
您可以使用bash .. tail。和head命令
cat file.sql | head -n 15 > head.sql
用行数替换15
或将头替换为尾...用于文件的底部