繁体   English   中英

从bash中的变量中提取除最后一个字段外的所有字段

[英]Extract all but last field from a variable in bash

我有一个类似于以下内容的文件:

01/01 THIS IS A DESCRIPTION 123.45
12/23 SHORTER DESC 9.00
11/16 DESC 1,234.00

三个字段:日期,描述,金额。 第一个字段将始终跟随一个空格。 最后一个字段将始终以空格开头。 但是中间字段通常将包含空格。

我知道bash / regex足够了解第一个和最后一个字段(例如, echo ${LINE##* }cut -f1 -d\\ )。 但是我如何获得中间领域? 基本上, 除了第一个字段和最后一个字段之外的所有内容。

您可以使用sed

$ sed -E 's/^[^[:space:]]*[[:space:]](.*)[[:space:]][^[:space:]]*$/\1/' file
THIS IS A DESCRIPTION
SHORTER DESC
DESC

或使用awk:

$ awk '{$1=$NF=""; sub(/^[ \t]*/,"")}1' file
# same output

您还可以使用cutrev删除第一和最后一个字段:

$ cut -d ' ' -f2- file | rev | cut -d ' ' -f2- | rev
# same output

或GNU grep:

$ grep -oP '^\H+\h\K(.*)(?=\h+\H+$)' file
# same output

或者,使用Bash循环和参数扩展

$ while read -r line; do line="${line#* }"; echo "${line% *}"; done <file
# same output

或者,如果要在Bash中将字段捕获为变量:

while IFS= read -r line; do
    date="${line%% *}"
    amt="${line##* }"
    line="${line#* }"
    desc="${line% *}"
    printf "%5s %10s \"%s\"\n" "$date" "$amt" "$desc"
done <file    

打印:

01/01     123.45 "THIS IS A DESCRIPTION"
12/23       9.00 "SHORTER DESC"
11/16   1,234.00 "DESC"

如果要删除第一个和最后一个字段,则可以扩展引用的参数扩展技术:

var=${var#* } var=${var% *}

单个#%会删除与该glob相匹配的最短子字符串。

您可以使用awk尝试以下一项:

awk '{$1="";$NF="";sub(/^[ \t]*/,"")}1' file_name 

bash:将行读入单词数组,然后从数组中选择所需的元素

while read -ra words; do 
    date=${words[0]}
    amount=${words[-1]}
    description=${words[*]:1:${#words[@]}-2}

    printf "%s=%s\n" date "$date" desc "$description" amt "$amount"
done < file

输出

date=01/01
desc=THIS IS A DESCRIPTION
amt=123.45
date=12/23
desc=SHORTER DESC
amt=9.00
date=11/16
desc=DESC
amt=1,234.00

这很有趣: ${words[*]:1:${#words[@]}-2}

  • 取字阵列的切片 ,从索引1(第2元件),用于“元素减去2的数目”的长度
  • 这些单词将使用空格分隔符连接成一个字符串。

请参阅Shell参数扩展,并向下滚动以了解${parameter:offset:length}讨论。


如果要在bash中使用正则表达式,则可以使用捕获括号和BASH_REMATCH数组

while IFS= read -r line; do 
    if [[ $line =~ ([^[:blank:]]+)" "(.+)" "([^[:blank:]]+) ]]; then 
        echo "date=${BASH_REMATCH[1]}" 
        echo "desc=${BASH_REMATCH[2]}" 
        echo "amt=${BASH_REMATCH[3]}"
    fi
done < file

与上面相同的输出。

请注意,在模式中空格需要加引号(或用反斜杠转义)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM