我遇到的情况是,我有几行,并且每行都需要两个不同的字段。具体来说,我有参考书目中的参考文献列表,我想获取姓氏和年份。
输入示例:
Aloise-Young, P.A. (1993). The development of self-presentation. Self-promotion in 6- to 10-year-old children. Social Cognition, 11, 201-222.
Banerjee, R. (2002). Children's understanding of self-presentational behavior: Links with mental-state reasoning and the attribution of embarrassment. Merril-Palmer Quarterly, 48, 378-404.
Bennett, M., & Wellman, H. (1989). The role of second-order belief-understanding and social context in children's self-attribution of social emotions. Social Development, 9, 126-130.
期望的输出:
Aloise-Young 1993
Banerjee 2002
Bennett 1989
我可以得到姓氏cat file | cut -d, -f1
我可以得到岁月cat file | grep -o "[[:digit:]]\{4\}"
我的问题是,现在我有两个独立的输出,但我不知道如何以我想要的方式组合它们。有任何想法吗?我怀疑也许awk
可以做我需要的事情。
答案1
当文本处理对于基本工具来说太困难时,请尝试awk。
awk -F , '{last_name = $1; sub(/\).*/, ""); sub(/.*\(/, ""); print last_name, $0}'
sed 与此差不多——可读性较差,但 awk 缺乏反向引用。
sed -n 's/^\([^,]*\),[^(]*(\([^()]*\)).*/\1 \2/p'
对于这个特定的任务,Perl 总体上要容易一些。您可以使用非贪婪重复运算符*?
来确保捕获该行的第一个括号部分。
perl -l -ne '/^([^,]*),.*?\(([^()]*)\)/ and print "$1 $2"'
答案2
我将您的代码片段放入名为 alois 的文件中:
sed -r 's/^([^ ,]+)[^0-9]+([0-9]+).*$/\1 \2/' alois
Aloise-Young 1993
Banerjee 2002
Bennett 1989
快速解释:我们使用 sed 的搜索和替换功能s/模式/替换/
^([^ ,]+) 的意思是:从行的开头取出任何不是空格或 a 的内容,并记住它们。 (这就是括号的作用)。
[^0-9]+ 查找任何非数值的内容,但忽略它。
([0-9]+) 获取并记住任何连续数字
.*$ 将其他所有内容匹配到行尾。
\1 \2 将所有匹配的内容(整行)替换为上面记住的值。
答案3
一般来说,您可以将命令的输出与paste
过程替换连接起来<(...)
,因此在您的情况下,这是可行的:
paste -d ' ' <(cut -d, -f1 file) <(grep -o "[[:digit:]]\{4\}" file)
输出:
Aloise-Young 1993
Banerjee 2002
Bennett 1989
但这需要传递file
两次,这是不必要的,因此您可能应该使用一种可以一次性抓取两个项目的工具,例如sed
,awk
等。
答案4
不性感,但您可以将文本从第一个逗号修剪到第一个左括号。用空格替换所有内容。然后只需将字符从第一个右括号修剪到行尾即可。
1. convert this => , ..... ( to a space
2. convert this => )........ to nothing
命令
$ cat file | sed 's/,.*(/ /' | sed 's/).*//'
Aloise-Young 1993
Banerjee 2002
Bennett 1989