如何在shell脚本中提取字符串的前两个字符?

152

例如,给定以下内容:

USCAGoleta9311734.5021-120.1287855805

我想要仅提取:

US

7
谢谢大家。最终我使用了'cut -c1-2',说实话我甚至不知道有'cut'这个命令。虽然我觉得我在命令行方面很有经验,但显然我还有很多需要学习的地方。 - Greg
1
@Greg,请注意cut是作为单独的进程运行的 - 它将比我在答案中同时发布的内部bash解决方案慢。这不会有任何影响,除非你正在处理大型数据集,但你需要记住这一点。 - paxdiablo
实际上,我认为这行代码可能会在每个报告中执行大约50,000次。所以我可能会选择内部Bash方法 - 正如你所说,这将节省一些非常需要的资源。 - Greg
15个回答

1
如果您的系统使用不同的shell(而不是bash),但您的系统有bash,那么您仍然可以通过使用变量调用bash来使用bash的内在字符串操作。
strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"

这个方法与主要答案使用相同的方式,只有在您没有使用bash时才会调用它。 - palswim
不幸的是,这会带来调用另一个进程的所有开销,但有时这种开销并不像简单和熟悉那样重要。 - palswim

1

如何考虑Unicode + UTF-8

对于那些对Unicode字符而不仅仅是字节感兴趣的人,让我们进行一个快速测试。在UTF-8中,每个重音元音字符áéíóú由两个字节组成。

printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 awk '{print substr($0,1,3);exit}'
printf 'áéíóú' | LC_CTYPE=C awk '{print substr($0,1,3);exit}'
printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 head -c3
echo
printf 'áéíóú' | LC_CTYPE=C head -c3

我们得到:
áéí
á
á
á

因此我们可以看到只有awk+LC_CTYPE=en_US.UTF-8考虑了UTF-8字符,而其他方法只考虑了三个字节。我们可以通过以下方式进行确认:

printf 'áéíóú' | LC_CTYPE=C head -c3 | hd

这表示:

00000000  c3 a1 c3                                          |...|
00000003

c3本身是垃圾,不会在终端上显示,所以我们只看到了á

awk + LC_CTYPE=en_US.UTF-8实际上返回了6个字节。

我们也可以使用等效的测试:

printf '\xc3\xa1\xc3\xa9\xc3\xad\xc3\xb3\xc3\xba' | LC_CTYPE=en_US.UTF-8 awk '{print substr($0,1,3);exit}'

如果您需要一个通用参数:

n=3
printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 awk "{print substr(\$0,1,$n);exit}"

关于Unicode + UTF-8的更具体问题:https://superuser.com/questions/450303/unix-tool-to-output-first-n-characters-in-an-utf-8-encoded-file

相关链接:https://unix.stackexchange.com/questions/3454/grabbing-the-first-x-characters-for-a-string-from-a-pipe

在Ubuntu 21.04上进行了测试。


0

这可能是你想要的:

my $string = 'USCAGoleta9311734.5021-120.1287855805';

my $first_two_chars = substr $string, 0, 2;

参考资料:substr


1
考虑到他/她可能会从shell中调用此命令,更好的形式应该是 perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805' - Chas. Owens

-1

代码

if mystring = USCAGoleta9311734.5021-120.1287855805

    print substr(mystring,0,2)

会打印出 US。

其中 0 是起始位置,2 是要读取的字符数。


说起来...那不是GW-BASIC吗?哦,等等,那是awk。抱歉,我一开始没看出来。 - Dennis Williamson

-1
perl -ple 's/^(..).*/$1/'

1
你忘记将字符串输出了。 - Chas. Owens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接