从bash中读取txt文件的值

时间:2017-03-13 14:00:53

标签: bash sed grep

我试图从文本文件中读取值。

我的test1.txt看起来像

sub1    1   2   3
sub8    4   5   6

我想获得价值观' 1 2 3'当我指定' sub1'。

我最接近的是:

subj="sub1"
grep "$subj" test1.txt

但答案是:

sub8    4   5   6

我已经读过grep为您提供了匹配的下一行,因此我尝试将文本文件更改为以下内容:

test2.txt看起来像:

sub1    
1   2   3

sub8    
4   5   6

然而,当我输入

grep "$subj" test2.txt

答案是:

sub1

它应该是超级简单的东西,但我已经尝试过awk,seg,grep,egrep,cat,没有人正在工作......我还读了一些相关的帖子,但没有一个真的有用

7 个答案:

答案 0 :(得分:1)

Awk有效:awk '$1 == "'"$subj"'" { print $2, $3, $4 }' test1.txt

该命令为test1.txt中的所有行输出字段2,3和4,其中第一个字段为$subj(即:名为subj的变量的内容)。

答案 1 :(得分:0)

grep "sub1" test1.txt | cut -c6-

grep -A 1 "sub1" test2.txt | tail -n 1

答案 2 :(得分:0)

使用原始文本文件格式:

target=sub1
while IFS=$' \t\n' read -r -d $'\r' key values || [[ $key ]]; do
  if [[ $key = "$target" ]]; then
    echo "Found values: $values"
  fi
done <test1.txt

这不需要外部工具,仅使用内置于bash本身的功能。请参阅BashFAQ #1

正如在评论调试过程中出现的那样,如果您有传统的Apple格式文本文件(仅限CR换行符),那么您可能需要更多类似的内容:

awk

或者,使用target="sub1" awk -v target="$target" '$1 == target { $1 = ""; print; }' <test1.txt (对于标准UNIX文本文件):

target="sub1"
tr '\r' '\n' <test1.txt | awk -v target="$target" '$1 == target { $1 = ""; print; }'

...或者,对于只有CR的换行文件:

awk

如果正在读取的文本文件很小,则此版本会较慢(因为awk,因为任何其他外部工具都需要时间来启动);但是如果它很大就会更快(因为{{1}}的操作比bash的内置命令要快得多)。

答案 3 :(得分:0)

Sed也有效:sed -n -e 's/^'"$subj"' *//p' file1.txt

在删除匹配的单词和后面的空格后,它会在一行的开头输出与$subj匹配的所有行。如果使用TAB,则空格应替换为[[:space:]]

答案 4 :(得分:0)

有很多方法可以做到这一点(和我给你的更短/更有效的答案),但我假设你是bash的初学者,因此我会给你一些简单的东西理解:

egrep "^$subj\>" file.txt | sed "s/^\S*\>\s*//"

egrep "^$subj\>" file.txt | sed "s/^[^[:blank:]]*\>[[:blank:]]*//"

第一部分egrep将在file.txt中的行尾处搜索主题(这是^符号在grep字符串中的作用)。它也在寻找一个完整的单词(\>正在寻找单词边界的结尾 - 这种方式sub1与文件中的sub12不匹配。)注意你必须使用egrep获取\>,因为默认情况下grep无法识别该转义序列。找到线后,egrep然后将其输出传递给sed,这将剥离第一个单词并从每一行尾随空格。同样,^命令中的sed符号指定它只应在行的开头匹配。 \S*告诉它尽可能多地读取非空格字符。然后\s*告诉sed尽可能多地吞噬空白。 sed然后将所有与之匹配的内容替换为任何内容,留下其他内容。

顺便说一句,Stack溢出中有一个帮助页面,它告诉你如何格式化你的问题(我猜这就是你得到一个downvote的原因)。

--------------编辑---------

正如所指出的,如果您使用的是Mac或类似的东西,则必须使用[:alnum:]代替\S[:blank:]代替\s { {1}}表达式(因为它们可以移植到所有平台)

答案 5 :(得分:0)

你做得对,但看起来test1.txt中有错误的值。

使用grep foo,你可以获得所有带有foo的行。使用grep -m1 foo仅在其中找到包含foo的第一行。

然后你可以使用cut -d" " -f2-来获取foo背后的所有值,同时用空格分隔。

最后命令看起来像这样......

$ subj="sub1"
$ grep -m1 "$subj" test1.txt | cut -d" " -f2-

但是这可以解释为什么你首先找不到sub1。 您是否阅读了正确的文件?

答案 6 :(得分:0)

awk '/sub1/{ print $2,$3,$4 }' file
1 2 3

会发生什么?在regexp / sub1 /之后打印三个以下字段。 有什么缺点吗?它影响了空间。