ฉันเบื่อดังนั้นนี่คือวิธีการอีกสองสามวิธีเกี่ยวกับการเชื่อมไฟล์เข้ากับตัวเองซึ่งส่วนใหญ่head
เป็นไม้ยันรักแร้ ให้อภัยฉันถ้าฉันอธิบายตัวเองให้มากเกินไปฉันแค่ชอบพูดสิ่งต่าง ๆ : พี
สมมติว่าN
เป็นจำนวน concatenations 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
ครั้ง
กล่าวว่าMATHอยู่ที่นี่ไม่มากก็น้อย: MATH (ส่วนสำคัญ)
มันเป็นสิ่งที่ภาคการศึกษาแรกวิทยาการคอมพิวเตอร์ แต่จะได้รับในขณะที่ตั้งแต่ผมทำหลักฐานการเหนี่ยวนำดังนั้นฉันไม่สามารถได้รับมากกว่านั้น ... (ยังเป็นระดับของการเรียกซ้ำนี้สวยที่รู้จักกันดีที่จะเป็น2^Loops
เช่นนั้นนั่นก็คือ .... )
POSIX
ฉันใช้บางสิ่งที่ไม่ใช่ posix แต่สิ่งเหล่านี้ไม่จำเป็น สำหรับวัตถุประสงค์ของฉัน:
yes() { while true; do echo "$1"; done; }
โอ้ฉันใช้มันเท่านั้น โอ้ส่วนนี้มีอยู่แล้วที่นี่ ...
วิธีการ
head
ด้วยการติดตาม linecount
ln=$linecount
for i in $(seq 1 $N); do
<file head -n $ln >> file;
ln=$((ln*2))
done
ไม่มีไฟล์ temp, cat ไม่มีแม้แต่คณิตศาสตร์มากเกินไปความสุขทั้งหมด
tee
กับMATH
<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file
นี่tee
คือการอ่านจากfile
แต่จะต่อท้ายตลอดดังนั้นมันจะทำการอ่านไฟล์ซ้ำจนกว่าhead
จะหยุด และเรารู้ว่าเมื่อมีการหยุดมันเพราะMATH การต่อท้ายผ่านไปผมก็เลยใช้ไฟล์ temp คุณสามารถตัดขอบส่วนเกินได้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
}
สำหรับตอนนี้ฉันหวังว่าคำตอบนี้จะไม่รบกวนใคร ฉันทดสอบพวกเขาทั้งหมดหลายครั้ง แต่ฉันเป็นเพียงผู้ใช้เปลือกหอยสองปีดังนั้นจำไว้ว่าฉันเดา ตอนนี้จะนอนหลับ ...
rm $tmp