我有以下 bash 命令,它返回超过 2 行的标题和 URL 对。
curl -s https://uk.reuters.com/assets/jsonWireNews |
awk '/"url":|"headline":/' |
cut -d'"' -f4 |
awk 'NR % 2 == 0 {sub(/^/,"https://uk.reuters.com")} {print}'
对于前 3 个标题,输出:
'Hamilton' takes centre stage in London's West End
https://uk.reuters.com/article/uk-britain-theatre-hamilton/hamilton-takes-centre-stage-in-londons-west-end-idUKKBN1EG02I
IAG among bidders chosen for Austrian airline Niki - sources
https://uk.reuters.com/article/uk-air-berlin-niki/iag-among-bidders-chosen-for-austrian-airline-niki-sources-idUKKBN1EG1BM
Oil eases from highs but OPEC cuts still support market
https://uk.reuters.com/article/uk-global-oil/oil-eases-from-highs-but-opec-cuts-still-support-market-idUKKBN1EG06G
我想成为头条新闻,即从第一行开始的每隔一行,以粗体显示:
《汉密尔顿》成为伦敦西区的焦点 https://uk.reuters.com/article/uk-britain-theatre-hamilton/hamilton-takes-centre-stage-in-londons-west-end-idUKKBN1EG02I IAG 是奥地利 Niki 航空公司选定的竞标者之一 - 消息人士 https://uk.reuters.com/article/uk-air-berlin-niki/iag-among-bidders-chosen-for-austrian-airline-niki-sources-idUKKBN1EG1BM 油价从高位回落,但欧佩克减产仍支撑市场 https://uk.reuters.com/article/uk-global-oil/oil-eases-from-highs-but-opec-cuts-still-support-market-idUKKBN1EG06G
答案1
尝试这个
#!/bin/bash
curl -s https://uk.reuters.com/assets/jsonWireNews |
awk '/"url":|"headline":/' |
cut -d'"' -f4 |
awk '/^\// { print "\033[0mhttps://uk.reuters.com:" $0; next } {print "\033[1m" $0 }'
如果匹配“^/”的开头,则打印非粗体的 bash 转义,然后转到下一行。默认打印在每行前面加上 bash 转义粗体前缀。
答案2
您在问题的第一个版本中的想法是正确的,问题只是如何获取 to 打印的控制代码,tput
以便awk
它可以打印它们。
变量和命令替换不会在单引号 ( ''
) 内展开,因此我们需要使用双引号。但是在awk
代码中使用它们可能会很尴尬(没有双关语的意思),因为可能还有其他字符需要转义。我们可以关闭单引号并在我们想要扩展的部分的持续时间内启动双引号字符串:
$ 粗体=“$(tput 粗体)” $正常=“$(tput sgr0)” $ echo -e 'foo\nbar\ndoo' | awk '{if (NR % 2) print "'"$bold"'" $0 "'"$normal"'";否则打印;}' 富 酒吧 杜
(在 中"'"$bold"'"
,第一个"
是文字,是 awk 代码的一部分,'
末尾是单引号字符串,"
开始是双引号字符串,其他"'"
顺序反过来也是一样。)
这有点难看。另一种方法是将控制代码awk
作为变量传递:
$ echo -e 'foo\nbar\ndoo' | awk -vbold="$bold" -vnormal="$normal" '{if (NR % 2) 打印粗体 $0 正常;否则打印;}' 富 酒吧 杜
(当然我们可以将它们传递到环境中。)
答案3
快速浏览后man tput
我尝试了:
$ bold=`tput smso`
$ normal=`tput rmso`
$ echo "${bold}Please type in your name: ${normal}\c"
它似乎起作用了......所以这应该给你足够的继续下去的机会,是吗?
答案4
perl
这是使用LWP
、JSON
和Term::ANSIColor
模块 来实现此目的的一种方法。Term::ANSIColor
是一个核心 perl 模块,但是LWP
和JSON
都是CPAN模块。它们是非常常用的模块,因此可能可以为您的发行版预先打包(例如在 debian 等上apt-get install libjson-perl libwwww-perl
)
#!/usr/bin/perl
use strict;
use LWP::UserAgent;
use JSON;
use Term::ANSIColor;
my $bold = color('bold');
my $reset = color('reset');
my $base='https://uk.reuters.com'
foreach my $url (@ARGV) {
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(GET => $url);
my $res = $ua->request($req);
if ($res->is_success) {
foreach my $h ( @{ decode_json($res->content)->{headlines} }) {
print $bold, $h->{headline}, $reset, "\n", $base, $h->{url}, "\n\n";
};
} else {
die "Error processing '$url': ", $res->status_line, "\n";
}
}
这不需要curl
或wget
或多次调用awk
和/或cut
(这种丑陋是促使我写答案的原因 - 作为一般规则,如果您正在管道grep
或awk
进入自身,那么您就做错了。管道cut
或的同上grep
into awk
-awk
可以做这两个可以做的一切以及更多perl
),或者其他任何事情。
将其另存为,例如./bold-2nd.pl
,使其可执行chmod
,然后像这样运行:
$ ./bold-2nd.pl https://uk.reuters.com/assets/jsonWireNews 苏格兰皇家银行支付 1.25 亿美元解决加州抵押贷款债券索赔 https://uk.reuters.com/article/uk-rbs-settlement/rbs-to-pay-125-million-to-settle-california-mortgage-bond-claims-idUKKBN1EH053 司机因澳大利亚车辆袭击事件被指控谋杀未遂 https://uk.reuters.com/article/uk-australia-attack/driver-charged-with-attempted-murder-over-australian-vehicle-attack-idUKKBN1EH044 易捷航空表示其他航空公司对从泰格尔起飞的支线航班感兴趣 https://uk.reuters.com/article/uk-air-berlin-ma-easyjet/easyjet-says-other-airlines-interested-in-feeder-flights-from-tegel-idUKKBN1EH04W [...]
这个版本的脚本可以在命令行上处理多个 URL(当然,它们都需要返回相同的 json 格式的数据……或者至少与 aheadline
和 aurl
字段极其相似)。
顺便说一句,我让它在每篇文章之间打印一个空行。我发现这更具可读性。
如果您想使用curl
而不是 perl 模块来进行获取LWP
,则脚本会更简单:
#!/usr/bin/perl
use strict;
use JSON;
use Term::ANSIColor;
my $bold = color('bold');
my $reset = color('reset');
my $base='https://uk.reuters.com'
undef $/;
my $json = <>; # slurp in entire stdin
foreach my $h ( @{ decode_json($json)->{headlines} }) {
print $bold, $h->{headline}, $reset, "\n", $base, $h->{url}, "\n\n";
};
运行此版本:
$ curl -s https://uk.reuters.com/assets/jsonWireNew | ./bold-2nd.pl
请注意,两个版本的粗体脚本都使用 json 解析器来实际解析 json 数据,而不是依赖正则表达式来搜索与特定模式匹配的行。正如之前多次指出的,使用正则表达式解析 json、html、xml 或任何类似的结构化数据格式是不可靠且脆弱的。在简单的情况下,它可以工作,但即使输入格式的微小变化也可能会破坏脚本(例如,如果Reuters 停止在每个数据元素和记录之间使用换行符输出漂亮打印的 json,并开始仅打印一行json 的任何基于行的正则表达式模式匹配器都会中断)
最后,(或LWP)获取的json数据curl
如下所示:
{ "headlines": [
{ "id": "UKKBN1EH044",
"headline": "Driver charged with attempted murder over Australian vehicle attack",
"dateMillis": "1514003249000",
"formattedDate": "3m ago",
"url": "/article/uk-australia-attack/driver-charged-with-attempted-murder-over-australian-vehicle-attack-idUKKBN1EH044",
"mainPicUrl": "https://s4.reutersmedia.net/resources/r/?m=02&d=20171223&t=2&i=1216634499&w=116&fh=&fw=&ll=&pl=&sq=&r=LYNXMPEDBM04W"
},
]}
so、id
、dateMillis
、formattedDate
和mainPicURL
也可用于打印或在 perl $h
hashref 变量中用于其他用途,以及我们正在打印的headline
和。url