假设我在 bash 中有两个变量:
MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"
我想检测变量何时实际包含多行文本,而忽略多余的尾随换行符。
所以这:
if [ some test on "$MULTILINE" ]; then echo 'yes'; else echo 'no'; fi
将打印yes
,并且这样:
if [ some test on "$SINGLE_LINE" ]; then echo 'yes'; else echo 'no'; fi
将打印no
。
就我的具体情况而言,我认为我不需要担心前导空行,但知道如何做到这一点也不会有什么坏处。
我怎样才能做到这一点?
答案1
我知道的最简单的解决方案是:
if (( $(grep -c . <<<"$MULTILINE") > 1 ))
例如:
VAR="a
b"
if (( $(grep -c . <<<"$VAR") > 1 )); then
echo VAR has more than one line
else
echo VAR has at most one line
fi
==>
VAR has more than one line
上述代码忽略了所有空白行:前导、尾随和内部。但请注意,除非至少有两条非空白行,否则不可能有内部空白行,因此它的存在无法改变在修剪前导和尾随空白行后是否有多行的问题。
答案2
$ echo "$MULTILINE" | wc -l 2 $ echo "$SINGLE_LINE" | wc -l 2 $ echo “$SINGLE_LINE” | sed -re'/^$/d'| wc -l 1 $ echo “$MULTILINE” | sed -re'/^$/d'| wc -l 2
看https://stackoverflow.com/questions/16414410/delete-empty-lines-using-sed
有关如何使用 sed 修剪/删除空格和空行的更多信息。
现在写下您在引号内的if expression ...
用途 $( ... )
以获取行数,并根据该数字进行测试:
如果 [ "$(echo "$MULTILINE" | sed -re '/^$/d' | wc -l)" -gt 1 ]; 然后 echo ‘多行’; 别的 回显‘单线或无线’; 菲
答案3
稍作修改此代码应该可以。您可以将其放入自己的脚本中以供重复使用,如下所示:
#!/bin/bash
nlhit=""
for (( i=0; i<${#1}; i++ )); do
if [[ "${1:$i:1}" == $'\n' ]]; then
nlhit="1"
elif [[ "$nlhit" == "1" ]]; then
exit 1
fi
done
exit 0
然后您可以像这样使用它(假设您将前一个脚本命名为multiline-check.sh
):
#!/bin/bash
EMPTYLINE=""
BLANKLINE=" "
ONLYLINES="
"
MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"
SECOND_LINE="
I begin with a newline"
echo -n "EMPTYLINE Check: "
multiline-check.sh "$EMPTYLINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi
echo -n "BLANKLINE Check: "
multiline-check.sh "$BLANKLINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi
echo -n "ONLYLINES Check: "
multiline-check.sh "$ONLYLINES"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi
echo -n "MULTILINE Check: "
multiline-check.sh "$MULTILINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi
echo -n "SINGLE_LINE Check: "
multiline-check.sh "$SINGLE_LINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi
echo -n "SECOND_LINE Check: "
multiline-check.sh "$SECOND_LINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi
答案4
忽略尾随的空行
以下是使用的方法awk
:
echo "$TEST" | tac | awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }' && echo "Found A Single Line"
怎么运行的:
回显“$TEST”
这将获取我们感兴趣的任何 shell 变量并将其发送到标准输出。
tac
这会反转行的顺序,以便首先返回最后一行。执行后
tac
,尾行将成为首行。(该名称
tac
与 相反,cat
因为它tac
执行的操作cat
相反。)awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }'
这将第一个非空行的行号存储在变量中
f
。读入所有行后,它会f
与总行数进行比较NR
。如果f
等于NR
,则我们只有一行(忽略初始空白),并以代码 0 退出。如果第一个空白行后有一行或多行,则它以代码 ` 退出。&& echo "Found A Single Line"
如果
awk
以代码 0 退出,则echo
执行该语句。
忽略前导和尾随的空行
通过创建一个附加awk
变量,我们可以扩展测试以忽略前导和尾随的空行:
echo "$TEST" | awk 'first==0 && /./ {first=NR} /./ {last=NR} END{if(first==last){exit 0}; exit 1 }' && echo " Found A Single Line"
因为此版本的awk
代码处理前导和尾随空白,tac
所以不再需要。
awk
一次处理一段代码:
first==0 && /./ {first=NR}
如果变量
first
为零(或者尚未设置)且行中有一个字符(任何字符),则设置first
为行号。awk
读完行后,first
将设置为第一个非空白行的行号。/./ {last=NR}
如果行中有字符,则将变量设置
last
为当前行号。awk
读取完所有行后,此变量将具有最后一个非空白行的行号。END{if(first==last){exit 0}; exit 1 }
此命令在读取完所有行后执行。如果
first
等于last
,则我们已看到零或行非空白行,并awk
退出并显示代码0
。否则,它将退出并显示代码。shell 脚本可以像往常一样使用语句或或来1
测试退出代码。if
&&
||