bash 扩展为相同的值而不是 sed 命令中的逐行值

bash 扩展为相同的值而不是 sed 命令中的逐行值

我有一个包含数字的文件,其中包含numbers.txt,如下所示。

9374541632553  
51243747879841  
32030098896914  
84654557358238  
11000656847765

我想将其转换为以下格式。

<item>9 3 7 4 5 4 1 6 3 2 5 5 3 <tag>out="9374541632553" 
<item>5 1 2 4 3 7 4 7 8 7 9 8 4 1 <tag>out="51243747879841" 
<item>3 2 0 3 0 0 9 8 8 9 6 9 1 4 <tag>out="32030098896914"
<item>8 4 6 5 4 5 5 7 3 5 8 2 3 8 <tag>out="84654557358238"
<item>1 1 0 0 0 6 5 6 8 4 7 7 6 5 <tag>out="11000656847765"

我正在使用以下命令来转换它。

cat numbers.txt | while read line; do sed -r "s/([0-9])/\1/g; s/([0-9])/\1 /g ; s/^/<item>/g; s/$/<tag>out="\$line/g" ; done

但我得到的输出如下:

<item>5 1 2 4 3 7 4 7 8 7 9 8 4 1 <tag>out="9374541632553
<item>3 2 0 3 0 0 9 8 8 9 6 9 1 4 <tag>out="9374541632553
<item>8 4 6 5 4 5 5 7 3 5 8 2 3 8 <tag>out="9374541632553
<item>1 1 0 0 0 6 5 6 8 4 7 7 6 5 <tag>out="9374541632553
<item>3 3 2 1 6 7 8 2 0 9 3 8 4 2 <tag>out="9374541632553

任何人都可以告诉我为什么最后一列只打印第一行而不是逐行值。
输出中的第一行怎么样?
解释所需的命令以获取所需的输出。

答案1

您可以在不循环的情况下执行此操作awk

awk '{a=$1;gsub(/./,"& ",$1); print "<item>"$1"<tag><out>=""\""a"\""}' numbers.txt

输出:

<item>9 3 7 4 5 4 1 6 3 2 5 5 3 <tag><out>="9374541632553"
<item>5 1 2 4 3 7 4 7 8 7 9 8 4 1 <tag><out>="51243747879841"
<item>3 2 0 3 0 0 9 8 8 9 6 9 1 4 <tag><out>="32030098896914"
<item>8 4 6 5 4 5 5 7 3 5 8 2 3 8 <tag><out>="84654557358238"
<item>1 1 0 0 0 6 5 6 8 4 7 7 6 5 <tag><out>="11000656847765"

解释:

  • 首先我们将第一个字段存储$1在变量中a
  • 将每个字符替换$1为其自身,后跟空格
  • 最后按所需顺序打印所有内容。
  • 一个有点棘手的部分是在\"应该引用本身的地方打印双引号

编辑(删除最后一个空格):

awk '{a=$1;gsub(/./,"& ",$1); printf "<item>"$1"\b<tag><out>=""\""a"\"\n"}' numbers.txt

<item>9 3 7 4 5 4 1 6 3 2 5 5 3<tag><out>="9374541632553"
<item>5 1 2 4 3 7 4 7 8 7 9 8 4 1<tag><out>="51243747879841"
<item>3 2 0 3 0 0 9 8 8 9 6 9 1 4<tag><out>="32030098896914"
<item>8 4 6 5 4 5 5 7 3 5 8 2 3 8<tag><out>="84654557358238"
<item>1 1 0 0 0 6 5 6 8 4 7 7 6 5<tag><out>="11000656847765"

答案2

因为 和 都readsed标准输入获取数据。

while循环中,您将read第一行放入$line.然后sed开始:您不给它任何其他输入,因此它从 stdin 读取,这是cat numbers.txt.因此sed将消耗剩余的输入。由于您仍然处于 while 循环的第一次迭代中,因此 $line 变量不会改变

我会为此使用 perl :

perl -lne '($spaced = $_) =~ s/./$& /g; print qq{<item>$spaced<tag>out="$_"}' numbers.txt

答案3

这是您可以在 sed 中完成整个操作的一种方法:

sed '
    h; 
    s/./& /g;
    s/.*/<item>&<tag>out=/;
    G;
    s/\n\([0-9]*\)/"\1"/;
    ' numbers.txt

答案4

这个怎么样...

cat numbers.txt | while read line; do echo $line | sed -r "s/([0-9])/\1/g; s/([0-9])/\1 /g ; s/^/<item>/g; s/$/<tag>out=\"$line\"/g" ; done

或者,

cat numbers.txt | while read line; do echo "<item>$(echo $line | fold -w1 | paste -s -d' ') <tag>out=\"$line\""; done

相关内容