我从古腾堡计划 (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
的次数,以使其与连接到其自身的次数相同。file
file2
file
N
说数学大致如下:数学(要点)
这是第一学期的计算机科学内容,但是我已经有一段时间没有做过归纳证明了,所以我无法忘记它......(而且这类递归是众所周知的,所以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 从第二行开始输出