方法

方法

我从古腾堡计划 (Project Gutenberg) 中获取了一本纯文本文件书 (大约 0.5MB),我想将其连接到自身n以生成一个大型文本文件,以便对一些算法进行基准测试。有没有 Linux 命令可以用来实现这一点? cat听起来很理想,但似乎不能很好地将文件连接到自身,而且不能直接解决n问题的时间部分。

答案1

对我来说,这分为两个部分 - 首先 - 使用 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,则有‘重复’命令。

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

答案2

你当然可以用cat它来做这个:

$ cat /tmp/f
foo
$ cat /tmp/f /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

答案3

我很无聊,所以这里还有几种将文件连接到自身的方法,主要是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)

file给定一个称为的副本file2,是需要添加到total_repeats的次数,以使其与连接到其自身的次数相同。filefile2fileN

数学大致如下:数学(要点)

这是第一学期的计算机科学内容,但是我已经有一段时间没有做过归纳证明了,所以我无法忘记它......(而且这类递归是众所周知的,所以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停止。我们知道什么时候停止它,因为数学。附加内容太多了,所以我使用了一个临时文件。您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

答案4

对于有标题的文件

!cat sample.csv > large.txt # first write with header
!for i in {1..200}; do tail -n +2 sample.csv >> large.txt; done

-n +2 从第二行开始输出

相关内容