bash:将变量的第一行分配给变量


11

我有一个多行变量,我只想要该变量的第一行。以下脚本演示了该问题:

#!/bin/bash

STRINGTEST="Onlygetthefirstline
butnotthesecond
orthethird"

echo "  Take the first line and send to standard output:"
echo ${STRINGTEST%%$'\n'*}
#   Output is as follows:
# Onlygetthefirstline

echo "  Set the value of the variable to the first line of the variable:"
STRINGTEST=${STRINGTEST%%$'\n'*}

echo "  Send the modified variable to standard output:"
echo $STRINGTEST
#   Output is as follows:
# Onlygetthefirstline butnotthesecond orthethird

问题:为什么${STRINGTEST%%$'\n'*}在放置在echo命令后面时返回第一行,但是在分配之后放置空格时换行?


1
无法重现。它按预期对我有用。
2015年

1
也不能使用2.05b,3.1、3.2、4.0、4.1、4.2、4.3中的任何一个进行复制。听起来像是用户错误,例如尝试使用不支持$'...'bash 的shell运行它。
斯特凡Chazelas

Answers:


8

也许还有其他方法可以存档您想要做的事情,但这可行

#!/bin/bash

STRINGTEST="
Onlygetthefirstline
butnotthesecond
orthethird
"

STRINGTEST=(${STRINGTEST[@]})
echo "${STRINGTEST[0]}"

假设其中的行$STRINGTEST不包含空格或通配符。还要注意,空行(如该变量的第一行)将被忽略。
斯特凡Chazelas

3
还要注意,使用STRINGTEST=(${STRINGTEST[@]})没有什么意义,并且等效于,STRINGTEST=($STRINGTEST)因为STRINGTEST先前已将其定义为标量(不是array)变量。
斯特凡Chazelas

10

可能不是最有效的,但一支班轮...

firstLine=`echo "${multiLineVariable}" | head -1`

2
为了简洁明了,我喜欢它。
彼得-恢复莫妮卡的时间

这个firstLine=`echo "${test_var}" | sed -n 1p如果你有一个理由去使用,而不是sed的也可以(例如,它意味着你可以同时执行的替代线路:echo "${test_var}" | sed -nE '1 s/# *(.*)/\1/p'
robenkleene

7

该代码适用于我在2.05b和4.3之间尝试过的所有bash版本。您更有可能尝试使用不支持$'...'引用形式的其他Shell运行该脚本。

$'...'句法不规范sh的语法(还)和仅支持(截至2015年5月22日和AFAIK)的ksh93(它起源)zshbash最近的版本mkshshFreeBSD的或最新版本

我的选择将是你试图运行与脚本sh,而不是bash和你sh是基于版本ashpdkshyash或者ksh88不支持它。

如果要使该代码与POSIX 2008兼容,则需要编写它:

STRINGTEST="Onlygetthefirstline
butnotthesecond
orthethird"

NL='
'
STRINGTEST=${STRINGTEST%%"$NL"*}
printf '%s\n' "$STRINGTEST"

然后,您可以用任何与POSIX兼容的外壳(bash或您的精简/快速外壳)来解释它sh

(请记住,在类似Bourne的shell中,在列表上下文中不加引号的变量具有非常特殊的含义)。


或者它可能是bash的旧版本。我可以用2.03重现该行为。
吉尔斯(Gilles)'所以

@Gilles是最后一个受支持的包含bash-2.03的操作系统(发行于16年前),可能是Solaris 8,它在3年前就停产了。这个假设似乎不太可能。
斯特凡Chazelas

1

这对我有用:

STRINGTEST="Some Text 1
Some Text 2
Some Text 3"

readarray -t lines < <(echo "$STRINGTEST")
echo "${lines[0]}"

它也适用于空行:

STRINGTEST="
Some Text 1
Some Text 2
Some Text 3"

readarray -t lines < <(echo "$STRINGTEST")
echo "${lines[0]}"

如果不愿意启动流程替换,那么最好将read一次替换为一个简单变量(而不是readarray加索引)。
彼得-恢复莫妮卡

0

使用内置的Bash read和here-string:

#!/usr/bin/env bash

STRINGTEST="
Some Text 1
Some Text 2
Some Text 3"


IFS=$'\n' read -r STRINGTEST <<<"$STRINGTEST"

使用POSIX参数扩展:

#!/usr/bin/env sh

STRINGTEST="
Some Text 1
Some Text 2
Some Text 3"

# Disables globing
set -f

# Field separator is newline only
IFS="
"

# No quotes, split lines as arguments because of IFS
set -- $STRINGTEST

# First argument is first line
STRINGTEST="$1"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.