【问题标题】:Read a file into variable preserving spaces and newlines将文件读入变量保留空格和换行符
【发布时间】:2020-11-28 16:48:33
【问题描述】:

正如问题所暗示的,我打算使用单个变量通过 bash 脚本以原始格式存储输入。

基本上当输入提示出现时,我会粘贴一些行,然后将存储的变量写入文本文件。经过一番搜索,我确实遇到了 readarray 但它没有将输入/粘贴存储在其原始粘贴状态

为了简单起见,假设我打算存储在变量中的输入/粘贴如下:

1
 2
  3
   4
    5

预期的脚本

#!/bin/bash
#the part i need help with ( Store the multiple line input/paste in raw format in a variable called let say test ) 
....
echo "$test" > test.txt
cat test.txt

这应该完全按照我在控制台输入提示期间粘贴的格式打印 1..5 / 也如上所示

编辑 - 可能有人好奇我的实际用例是什么,所以我举一个例子,我的粘贴在实际用例中实际上是什么。为了简单起见,我使用了 1..5 示例。

https://cdn.jwplayer.com/videos/XXXizsW4-32313922.mp4
  out=Lecture 01- AS 1 Theory.mp4
https://cdn.jwplayer.com/videos/XXX6XFPB-32313922.mp4
  out=Lecture 02- AS 1 Question.mp4
https://cdn.jwplayer.com/videos/XXXIeQNM-32313922.mp4
  out=Lecture 03- AS 2 Theory.mp4

我只会以这种格式粘贴文本

https://link
  out=Some-Name.mp4 ( 2 spaces before word out )

虽然我要粘贴 300,400 对这样的行(如果重要的话)。

【问题讨论】:

  • define: "readarray 但它不适合我的需要"
  • 它没有以原始格式将我的粘贴存储在变量中
  • “原始格式”是什么意思?您能否以明确的形式提供输入和预期输出的示例(可能是十六进制转储或$'C-style string\n',如果您需要包含控制代码或其他不可打印的字符)?
  • 通过原始格式,我的意思是它应该存储我在输入提示期间粘贴的内容。它应该保留所有缩进和空格
  • @tripleee 你去吧,我还添加了我的真实用例场景。我希望现在一切都清楚了

标签: linux bash unix awk sed


【解决方案1】:
$ cat 12345
1
 2
  3
   4
    5
$ cat 12.sh
#!/bin/bash

readarray -d '\n' lines

echo "$lines" > 12345.tmp
echo "$lines"
$ cat 12345 | ./12.sh
1
 2
  3
   4
    5

$ cat 12345.tmp
1
 2
  3
   4
    5

$

【讨论】:

  • 这是不正确的; $lines 不是数组,只是它的第一个元素。
  • 我看不出我的帖子和你的 (@tripleee) 之间的区别。两者都以相同的方式读取数据,所以在您的情况下,数据也(仅)在第一个元素中?
  • 好的,但我在readarray -d '\n' lines 中没有“$”。演示:ideone.com/0ODbmb
  • 那你为什么要使用数组呢? read -r -d 'no such separator no sirree' lines 不会那么混乱。 (仍然需要引用变量 echo。)演示:ideone.com/Zo2fsZ
  • 仍然“我想要一个数组,但没有一个数组的有用特性”是一个令人费解的解释。
【解决方案2】:

类似的东西:

#!/bin/bash

IFS= read -r -d $'\004' test
echo "$test" > /tmp/test.txt

粘贴输入后按 CTRL-D 并检查文件 /tmp/test.txt

【讨论】:

    【解决方案3】:

    给定:

    $ cat test.txt
     1
      2
       3
        4
         5
    

    几种方式:

    首先,您可以使用进程替换将文件内容读入单个变量:

    $ txt="$(cat test.txt)"
    $ echo "$txt"
     1
      2
       3
        4
         5
    

    或者,您可以逐行遍历文件的内容并保留格式:

    $ while IFS= read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done <test.txt
    ' 1'
    '  2'
    '   3'
    '    4'
    '     5'
    

    (删除printf "'%s'\n" 中的' 以从输出中删除那些)


    编辑

    您的编辑使您的问题不太清楚,但您似乎正在处理大量(您说 300,400 条)线对。

    如果是这样,最好的办法是使用awk 来处理线对:

    $ echo "https://cdn.jwplayer.com/videos/XXXizsW4-32313922.mp4
        out=Lecture 01- AS 1 Theory.mp4
    https://cdn.jwplayer.com/videos/XXX6XFPB-32313922.mp4
        out=Lecture 02- AS 1 Question.mp4
    https://cdn.jwplayer.com/videos/XXXIeQNM-32313922.mp4
        out=Lecture 03- AS 2 Theory.mp4"  | awk '!(NR%2){sub(/mp4/,"MP4 EVEN LINE")}1' 
    https://cdn.jwplayer.com/videos/XXXizsW4-32313922.mp4
        out=Lecture 01- AS 1 Theory.MP4 EVEN LINE
    https://cdn.jwplayer.com/videos/XXX6XFPB-32313922.mp4
        out=Lecture 02- AS 1 Question.MP4 EVEN LINE
    https://cdn.jwplayer.com/videos/XXXIeQNM-32313922.mp4
        out=Lecture 03- AS 2 Theory.MP4 EVEN LINE
    

    (从!(NR%2) 中删除! 以处理奇数对。)

    【讨论】:

      【解决方案4】:

      问题显然在于您如何编写变量。如果使用数组,写的时候需要正确引用。

      readarray -d $'\n' test
      printf '%s\n' "${test[@]}"
      

      或许也可以看看When to wrap quotes around a shell variable?

      【讨论】:

        【解决方案5】:

        如果这不是您所需要的全部,请发布一个新问题:

        $ foo=$(< file)
        $ printf '%s\n' "$foo"
        1
         2
          3
           4
            5
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-20
          • 1970-01-01
          • 2019-03-17
          • 2013-06-02
          相关资源
          最近更新 更多