Linux命令将文件连接到自身n次


31

我已经从Project Gutenberg中提取了一个纯文本文件书(大约0.5MB),我希望将其与自己的n时间连接起来,以便生成一个大的文本文件,可以对某些算法进行基准测试。我可以使用一个Linux命令来实现这一点吗? cat听起来很理想,但在将文件串联到自身上似乎玩起来不太好,而且不能直接解决问题的n时间部分。


2
使用某种循环,并追加?如此重复foo.txt >> bar.txt并将其包装在将多次运行命令的内容中?
Journeyman Geek

Answers:


35

对于我来说,这有两个部分-首先-使用cat将文本文件输出到标准输出,然后使用append将其添加到另一个文件-例如foo.txt >> bar.txt将foo.txt附加到bar.txt

然后运行n次

for i in {1..n};do cat foo.txt >> bar.txt; done

用您的数字替换该命令中的n

应该可以,其中n是您的数字

如果使用csh,则有“ repeat”命令。

重复的答案的相关部分从此处复制,我在默认的bash shell的ubuntu 11.04系统上对其进行了测试。


3
有趣的事实:这实际上无需替换'n'就可以了,在这种情况下,它将对ASCII'1'和ASCII'n'之间的每个字符执行一次正文(大约62次)。但是{1..12}会正确运行身体12次。
Arnout Engelen

1
您可能只想重定向整个管道,而不是在每次迭代中追加:for i in {1..n};do cat foo.txt; done > bar.txt
Toby Speight

2

我很无聊,因此这里有更多关于如何将文件连接到自身的方法,主要是使用head拐杖。如果我过度解释自己,请原谅我,我只是喜欢说些什么:P


假设N您要执行的自我串联数量为您的文件命名file

变量:

linecount=$(<file wc -l)

total_repeats=$(echo "2^$N - 1" | bc) # obtained through the power of MATH

total_lines=$((linecount*(total_repeats+1)))

tmp=$(mktemp --suffix .concat.self)

给定一个filecalled 的副本file2total_repeatsfile需要添加次数file2以使其与file连接到自身的N时间相同。

说的MATH或多或少在这里:MATH(要点)

这是第一学期的计算机科学课程,但是已经有一段时间了,因为我做了归纳证明,所以我无法克服它……(而且众所周知,此类递归也是2^Loops如此……)


POSIX

我使用了一些非posix的东西,但它们不是必需的。就我而言:

 yes() { while true; do echo "$1"; done; }

哦,我只是用那个。哦,好了,这个部分已经在这里...


方法


head 与线数跟踪。

ln=$linecount
for i in $(seq 1 $N); do
    <file head -n $ln >> file;
    ln=$((ln*2))
done

没有临时文件,没有猫,甚至还没有太多的数学,所有的快乐。


tee数学

<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file

tee是从中读取的内容,file但会永久附加在文件中,因此它将重复读取文件,直到head停止文件。而且我们知道什么时候可以因为MATH而停止它。追加过程完全失败,所以我使用了一个临时文件。您也可以修剪多余的线条file


eval,黑暗之王!

eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp
cat $tmp > file

这只是扩展cat file file file ...并评估了它。您也可以不使用该$tmp文件:

eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
  head -n $((total_lines-linecount)) >> file

通过在中间人和写操作之间放置一个中间人来进行第二个head“技巧” cat。您也可以欺骗cat另一个cat,但是行为不一致。尝试这个:

test_double_cat() {
    local Expected=0
    local Got=0
    local R=0
    local file="$(mktemp --suffix .double.cat)"
    for i in $(seq 1 100); do

        printf "" > $file
        echo "1" >> $file
        echo "2" >> $file
        echo "3" >> $file

        Expected=$((3*$(<file wc -l)))

        cat $file $file | cat >> $file

        Got=$(<file wc -l)

        [ "$Expected" = "$Got" ] && R="$((R+1))"
    done
    echo "Got it right $R/100"
    rm $file
}

sed

<file tr '\n' '\0' |
    sed -e "s/.*/$(yes '\0' | head -n $total_repeats | tr -d '\n')/g" |
        tr '\0' '\n' >> file

强制sed将整个文件作为一行读取,捕获所有文件,然后粘贴$total_repeats多次。

如果文件中包含任何空字符,这当然会失败。选择一个您不知道的那个。

find_missing_char() {
  local file="${1:-/dev/stdin}"

  firstbyte="$(<$file fold -w1 | od -An -tuC | sort -un | head -n 1)"
  if [ ! "$firstbyte" = "0" ]; then
    echo "\0"
  else
    printf "\\$(printf '%03o\t' $((firstbyte-1)) )"
  fi
}

现在小伙子们就这些了,我希望这个随心所欲的答案不会打扰任何人。我对它们全部进行了多次测试,但我只是两年的Shell用户,所以我想请记住这一点。现在睡觉...

rm $tmp


2

您当然可以使用cat

$ cat /tmp/f
foo
$ cat /tmp/foo /tmp/f
foo
foo

要获取$n副本,您可以使用yes管道连接到head -n $n

$ yes /tmp/f | head -n 10
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f

放在一起得出

yes /tmp/f | head -n $n | xargs cat >/tmp/output
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.