sed 's/\x0A\x0B/\x0C\x0D/g'
Avsak sed aj pri pouziti moznosti in-place (-i) vytvara novy subor, co zbytocne predlzuje cas. Tiez je tu ten problem, ze ak hexstring obsahuje newline character (0x0A), tak sed s tym ma problem a nic nenahradi. Da sa toto nejak vyriesit?#!/usr/bin/env python3
import sys
def findIndex(f, sa):
ri = 0
ra = []
sl = len(sa)
while True:
try:
b = f.read(1)
if (len(b) == 0):
raise EOFError()
ra.append(b[0])
except EOFError:
return -1
ri += 1
if (len(ra) > len(sa)):
ra.pop(0)
if (ra == sa):
return ri - sl
def write(f, index, s):
f.seek(index)
f.write(s)
def replace(fn, ih, oh):
f = open(fn, "rb+")
index = findIndex(f, list(bytes.fromhex(ih)))
if (index == -1):
print("Not found")
else:
write(f, index, bytes.fromhex(oh))
f.close()
if __name__ == '__main__':
if (len(sys.argv) != 4):
print("Usage: %s filename inhex outhex", sys.argv[0])
else:
replace(sys.argv[1], sys.argv[2], sys.argv[3])
No predpokladal som, ze nahradenie hex stringu v subore je vcelku trivialna a nie vynimocna zalezitost, takze ma celkom prekvapuje, ze na to nie je dostatok utilit...Za triviální a nikoli výjimečnou záležitost je v unixu považováno dokonce nahrazení textu v proudu bajtů, přičemž proud bajtů je obecnější věc, než jen soubor. Takže utilit na to existuje spousta. Vy ale na tu náhradu máte speciální předpoklady a speciální požadavky, ty obecné nástroje tedy nechcete použít.
Co sa tyka toho okamziteho zapisu, na Windows som pouzival HxD hexeditor, kde sa dal upravit priamo subor, tak som cakal, ze nieco podobne bude aj pre linux a v terminali...A ten HxD jste mohl použít dávkově? Unix je založený na tom, že má spoustu jednoduchých nástrojů, které můžete kombinovat. Takže to, co chcete udělat, samozřejmě je možné, akorát si musíte pospojovat použití vhodných nástrojů. Díky tomu pak ty nástroje můžete snadno používat dávkově.
Bez zaruky a bez krasy:#!/usr/bin/env python3
import sys
def findIndex(f, sa):
ri = 0
ra = []
sl = len(sa)
while True:
try:
b = f.read(1)
if (len(b) == 0):
raise EOFError()
ra.append(b[0])
except EOFError:
return -1
ri += 1
if (len(ra) > len(sa)):
ra.pop(0)
if (ra == sa):
return ri - sl
def write(f, index, s):
f.seek(index)
f.write(s)
def replace(fn, ih, oh):
f = open(fn, "rb+")
index = findIndex(f, list(bytes.fromhex(ih)))
if (index == -1):
print("Not found")
else:
write(f, index, bytes.fromhex(oh))
f.close()
if __name__ == '__main__':
if (len(sys.argv) != 4):
print("Usage: %s filename inhex outhex", sys.argv[0])
else:
replace(sys.argv[1], sys.argv[2], sys.argv[3])
to je hodne neefektivni. Pouzijte radeji mmap.
to je hodne neefektivni. Pouzijte radeji mmap.
Tohle mě zajímá. Soubor se čte sekvenčně, pravděpodobně s bufferováním. Zapisuje se stejně dlouhý řetězec, tudíž se v souboru nic neposouvá. Co na tom vylepší mmap?
#!/usr/bin/env python3
import sys
def regions(f):
chunkLength = 50000000
offset = 0
c1 = f.read(chunkLength)
while (len(c1) == chunkLength):
c2 = f.read(chunkLength)
yield offset, c1 + c2
c1 = c2
offset += chunkLength
yield offset, c1
def findIndex(f, s):
for offset, chunk in regions(f):
index = chunk.find(s)
if (index >= 0):
return offset + index
return -1
def write(f, index, s):
f.seek(index)
f.write(s)
def replace(fn, ih, oh):
f = open(fn, "rb+")
index = findIndex(f, bytes.fromhex(ih))
if (index == -1):
print("Not found")
else:
write(f, index, bytes.fromhex(oh))
f.close()
if __name__ == '__main__':
if (len(sys.argv) != 4):
print("Usage: %s filename inhex outhex", sys.argv[0])
else:
replace(sys.argv[1], sys.argv[2], sys.argv[3])
package main
import (
"flag"
"golang.org/x/exp/mmap"
"log"
"os"
"time"
)
var (
what, with, where string
)
func main() {
flag.StringVar(&what, "replace", "", "String to be replaced.")
flag.StringVar(&with, "with", "", "String to act as replacement.")
flag.StringVar(&where, "in", "", "Path to file.")
flag.Parse()
reader, err := mmap.Open(where)
if err != nil {
log.Fatal(err)
}
defer reader.Close()
file, err := os.OpenFile(where, os.O_WRONLY, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
start := time.Now()
defer func() {
log.Println("Elapsed time:", time.Now().Sub(start).String())
}()
var pos int
whatLen := len(what)
cpr := make([]byte, whatLen, whatLen)
first := what[0]
max := reader.Len()
for {
if pos >= max {
log.Println("no match found")
return
}
if reader.At(pos) == first {
if _, err := reader.ReadAt(cpr, int64(pos)); err != nil {
log.Fatal(err)
}
if string(cpr) == what {
if _, err := file.WriteAt([]byte(with), int64(pos)); err != nil {
log.Fatal(err)
} else {
log.Println("Success")
}
return
} else {
pos += whatLen
continue
}
}
pos++
}
}
#!/usr/bin/env python3
# vim:ts=4 sw=4:
import sys
import os
import mmap
if len(sys.argv) < 4:
print("Usage: "+sys.argv[0]+" file searchHex replaceHex")
sys.exit(-1)
(repl_from, repl_to) = [bytearray.fromhex(h) for h in sys.argv[2:4]]
repl_len = len(repl_from)
if repl_len != len(repl_to):
print("Error: search and replacement strings have different lengths")
sys.exit(-2)
filename=sys.argv[1]
with open(filename, "r+b") as f:
map = mmap.mmap(f.fileno(), 0)
idx = 0
while True:
idx=map.find(repl_from, idx)
if idx<0:
break;
map.seek(idx)
map.write(repl_to)
idx += repl_len
map.close()
Tu mas Go verziu(2mb), ale moc som to netestoval takze za nic nerucim.Při zběžném pohledu se mi zdá, že to bude fungovat korektně jen pokud je v hledaném řetězci každý byte unikátní.
https://en.wikipedia.org/wiki/Demand_paging
Cele nacitanie suboru vznika len v pripade ak robis "read all" operacie. Cize bezne sa subory prechadzaju riadok za riadkom, pripadne v blokoch, len malokedy sa nacitaju cele do pamete. Je jedno o aky jazyk ide.
3. Dovedu si samozřejmě představit, že je OS "chytrý" a dokáže podle potřeby uvolňovat kusy paměti, ale přijde mi to celé proti filosofii a smyslu toho mechanismu. Jednak on nemůže vědět, kam si budu chtít sáhnout hned v další operaci (tudíž se to celé může dost prodražit) a vůbec asi pro rychlou práci nechci takto nedeterministické chování systému.Smysl mmapu je právě v tom, že k datům přistupujete jako k souvislému bloku paměti, a OS se na pozadí stará o nahrávání příslušných bloků z disku do paměti a opačně o zápis na disk. Je to vlastně podobný mechanismus, jako swap, akorát se na disk zapisují jen změněná data a zapisují se do toho původního souboru.
3. Dovedu si samozřejmě představit, že je OS "chytrý" a dokáže podle potřeby uvolňovat kusy paměti, ale přijde mi to celé proti filosofii a smyslu toho mechanismu. Jednak on nemůže vědět, kam si budu chtít sáhnout hned v další operaci (tudíž se to celé může dost prodražit) a vůbec asi pro rychlou práci nechci takto nedeterministické chování systému.Smysl mmapu je právě v tom, že k datům přistupujete jako k souvislému bloku paměti, a OS se na pozadí stará o nahrávání příslušných bloků z disku do paměti a opačně o zápis na disk. Je to vlastně podobný mechanismus, jako swap, akorát se na disk zapisují jen změněná data a zapisují se do toho původního souboru.
Jo, a jak poznám, kdy mi to odswapuje a kolik to skutečně sežere paměti? Co jsi mi chtěl vlastně sdělit konkrétního?
Jo, a jak poznám, kdy mi to odswapuje a kolik to skutečně sežere paměti? Co jsi mi chtěl vlastně sdělit konkrétního?
to nepotrebujete vedet. Ani pri tom "sekvencnim" cteni neznate velikost bufferu.
Jo, a jak poznám, kdy mi to odswapuje a kolik to skutečně sežere paměti?Linux (a další systémy) funguje tak, že používá tzv. virtuální paměť. Každý proces má k dispozici svůj vlastní prostor virtuální paměti – třeba na x86 zařízeních má ta virtuální paměť standardně 4 GB, bez ohledu na to, že máte v počítači třeba jen 256 MB RAM. Operační systém se pak stará o mapování mezi touhle virtuální pamětí procesu a skutečnou RAM. A při tomhle mapování může dělat i to, že data nejsou fyzicky v paměti, ale dostanou se tam až v okamžiku, kdy chce proces k příslušné části paměti přistupovat. Dostat se tam mohou například i z disku – např. ze swapu, kam si je před tím operační systém odložil, když potřeboval fyzickou RAM pro jiné účely, a nebo ze souboru, který tvoří „podklad“ pod pamětí mapovanou mmapem.
Co jsi mi chtěl vlastně sdělit konkrétního?Jak doopravdy funguje mmap, a že funguje jinak, než si myslíte. Že při použití mmapu neřídí načítání ze souboru do paměti a zápis z paměti do souboru aplikace, ale operační systém. A že i když má aplikace přes mmap zpřístupněný celý soubor ve svém virtuálním adresním prostoru (ve virtuální paměti), neznamená to, že je celý ten soubor načtený ve fyzické RAM.