例如,给定:
USCAGoleta9311734.5021-120.1287855805
我只想提取:
US
例如,给定:
USCAGoleta9311734.5021-120.1287855805
我只想提取:
US
Answers:
如果使用的是bashshell(根据您的评论似乎是这样),则最有效的方法可能是使用参数扩展的sub-string变体:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
这将设置short为的前两个字符long。如果long少于两个字符,short将与它相同。
如果您要执行很多操作(如您提到的每个报告50,000次),则这种内嵌方法通常会更好,因为没有流程创建开销。所有使用外部程序的解决方案都将遭受该开销。
如果您还想确保最小长度,则可以在手之前将其填充,例如:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
这样可以确保长度少于两个字符的任何字符都在右边用句点填充(或其他一些字符,只需更改创建时使用的字符tmpstr)即可。尚不清楚您是否需要此功能,但我想我出于完整性考虑。
话虽这么说,外部程序有许多方法可以做到这一点(例如,如果您没有bash空的话),其中包括:
short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')
对于单行字符串,前两个(cut和head)是相同的-基本上,它们都只给您返回前两个字符。它们的不同之处cut在于,每行的前两个字符head为您提供整个输入的前两个字符
第三个使用awk子字符串功能提取前两个字符,第四个使用sed捕获组(使用()和\1)捕获前两个字符并用它们替换整行。它们都类似于cut-它们在输入中提供每行的前两个字符。
如果您确定您的输入是一行,则无所谓,它们都具有相同的效果。
printf '%s'替代echo的情况下有字符串中的字符怪异:stackoverflow.com/a/40423558/895245对于POSIX痴迷:head -c是不是POSIX,cut -c和awk substr是,sed \1不知道。
最简单的方法是
${string:position:length}
凡本提取$length将子$string在$position。
这是内置的bash,因此不需要awk或sed。
您已经获得了几个不错的答案,我将自己使用内置的Bash,但是由于您提出了问题sed,awk并且(几乎)没有人提供基于它们的解决方案,因此我向您提供以下这些:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
和
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
在awk一个应该是相当明显的,但这里的的解释sed之一:
substr($0,1,2)。
如果您在bash,可以说:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
这可能正是您所需要的……
如果要使用Shell脚本并且不依赖非posix扩展名(例如所谓的bashisms),则可以使用不需要分叉外部工具(例如grep,sed,cut,awk等)的技术,然后使您的脚本效率降低。在您的用例中,效率和posix的可移植性也许并不重要。但是如果是这样(或者只是一个好习惯),则可以使用以下参数扩展选项方法来提取shell变量的前两个字符:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
这使用“最小前缀”参数扩展来删除前两个字符(这是该${var#??}部分),然后使用“最小后缀”参数扩展(${var%部分)来从原始字符中删除所有但仅前两个字符的字符串值。
以前在“ 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;"
只是为了好玩,我将添加一些内容,尽管它们过于复杂和无用,但并未提及它们:
head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none
sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')
cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"
ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'
如果mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
会打印美国
其中0是开始位置,2是阅读方式
awk。抱歉,我一开始不能告诉。
这是你的追求吗?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
参考:substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'