如何正确使用cut从shell脚本中的字符串中获得所需的输出?

np8igboo  于 2023-04-07  发布在  Shell
关注(0)|答案(4)|浏览(149)
#!/bin/bash
list="john,do not target
martin,unknown"

for i in $list; do
     name=`echo ${i} | cut -f1 -d','`
     value=`echo ${i} | cut -f2 -d','`
     echo $value
done

由于do not target之间的白色,我为上面得到的输出是

do
not
target
unknown

我想要的输出是:

do not target
unknown
igetnqfo

igetnqfo1#

不需要cut(外部进程);你可以在Bash中这样做:

list='john,do not target
martin,unknown'

while IFS= read -r line; do
    name="${line%%,*}"
    value="${line#*,}"
    printf "'%s' : '%s'\n" "$name" "$value"
done <<< "$list"

但是,除非list来自您无法控制的输入(就格式而言),否则在Bash中有更好的方法来表示此类数据,例如关联数组。

declare -A list=(
    ['john']='do not target'
    ['martin']='unknown'
)

for name in "${!list[@]}"; do
    printf "'%s' : '%s'\n" "$name" "${list["$name"]}"
done

诚然,关联数组并不保持顺序;如果需要的话,你可以有一个额外的(整数索引的)数组,从数字Map到名称。

declare -a list=('john' 'martin')
declare -A data=(
    ['john']='do not target'
    ['martin']='unknown'
)

for name in "${list[@]}"; do
    printf "'%s' : '%s'\n" "$name" "${data["$name"]}"
done
x6yk4ghg

x6yk4ghg2#

read为我们进行拆分(通过IFS):

while IFS=, read -r name value      # split line of input on a comma; store 1st field in variable 'name', store rest of input in variable 'value'
do
    echo "${value}"
done <<< "${list}"

**注意:**这有一个额外的好处,即消除了当前代码每次通过循环时产生的4个子进程

这产生:

do not target
unknown
bxjv4tth

bxjv4tth3#

正如其他答案中所述,bash具有处理这类问题的工具,并且您不必(通常也不应该)调用外部实用程序。为了回答这个问题,或者如果您坚持使用cut,我建议如下使用:

list="john,do not target
martin,unknown"

cut -d, -f2 <<< "$list"

这将输出:

do not target
unknown
qc6wkl3g

qc6wkl3g4#

这里已经有了很好的答案,但是花一点时间看看你在做什么。

list="john,do not target
martin,unknown"

这不是一个列表,它是一个字符串-一个字符串,你在循环中使用,不加引号

for i in $list; do

我很确定这不是你想要的。当你说$list的时候,你得到的输出和在一个不带引号的echo中使用它的输出是一样的-

$: list="john,do not target
martin,unknown"
$: echo $list
john,do not target martin,unknown

所以你的意思是

for i in john,do not target martin,unknown; do

所以第一次i是“john,do”。第二次是“not”。等等。
一个简单的read将做你想做的事情,我想。

$: echo "$list"
john,do not target
martin,unknown

$: echo "$list">file

$: while IFS=, read -r name value; do echo "name=[$name] value=[$value]"; done < file
name=[john] value=[do not target]
name=[martin] value=[unknown]

$: while IFS=, read -r name value; do echo "name=[$name] value=[$value]"; done <<< "$list"
name=[john] value=[do not target]
name=[martin] value=[unknown]

所以,我会说,为了清晰地复制你所要求的内容,使用markp-fuso's solution,尽管对于你发布的片段所暗示的实际文字结果,我同意M. Nejat Aydin's-使用简单的cut

相关问题