Как @msw предположил, Вы - более обеспеченное создание ISO CD/DVD с помощью фактического инструмента, с помощью dd
как это может быть проблематичным. Особенно, если существует дефект в медиа. dd
не сделает ничего, чтобы попытаться восстановить это.
Если это - DVD I часто, времена включают в список справку dvdbackup
который был превосходен при создании копий DVD это k3b
копировал бы, но затем был бы неиграем. Когда я исследовал их в прошлом, DVD часто был временами, поцарапанными или дефектными, но все еще играемыми. dvdbackup
смог копировать их без проблемы.
Это шаги, которые я раньше в прошлом выполнял dvdbackup
:
$ cd /dir/where/you/save/the/dvd
# insert DVD to be copied
$ dvdbackup -M
$ genisoimage -dvd-video -udf -o movie.iso /dir/where/you/save/the/dvd
$ eject /dev/dvd
Это (далеко от элегантного) частичного решения вашей проблемы. Он использует первый столбец в качестве столбца ID (не должен быть первым, но вы обязательно должны иметь один) и представляют третье измерение суффикс
для хранения нескольких предложений одного и того же ключа. В конце концов, он пытается найти эти ключевые ключи файла 2, которые не были найдены в файле 1.
BEGIN {
IGNORECASE = 1
}
NR==1 {
for (i = 1; i <= NF; i++)
header[i] = $i
suffix = 0
previous_key=""
}
NR==FNR {
if ($1 == previous_key) {
suffix = suffix + 1
max_suffix[$1] = suffix
} else
suffix = 0
for (i = 1; i <= NF; i++) {
A[$1,suffix,i] = $i
}
key_count[$1] = key_count[$1] + 1
previous_key = $1
next
}
{
if ($1 == previous_key)
suffix = suffix + 1
else
suffix = 0
previous_key = $1
if (A[$1,suffix,1] != "") {
for (i = 2; i <= NF; i++)
if (A[$1,suffix,i] != $i) {
print header[1]"#-"$1": " header[i] "- " ARGV[1] " value= ", A[$1,suffix,i]" / " ARGV[2] " value= "$i
}
key_count[$1] = key_count[$1] - 1
}
else
for (i = 2; i <= NF; i++)
print header[1]"#-"$1": " header[i] "- " ARGV[1] " value= ", " / " ARGV[2] " value= "$i
}
END {
for (missing_key in key_count)
if (key_count[missing_key] > 0) {
for (suffix = max_suffix[missing_key] - key_count[missing_key] + 1; suffix <= C[missing_key]; suffix++)
for (i = 2; i <= NF; i++)
print header[1]"#-"missing_key": " header[i] "- " ARGV[1] " value= ", A[missing_key,suffix,i] " / " ARGV[2] " value= "
}
}
Существует предостережение: не подходящие записи в файле 2 всегда напечатаны в конце и не отсортированы в соответствии с положением в файл. Более того, сортировка этих линий является произвольным. Я думаю, что это можно взять из трубопровода результат в команду сортировка
.
У меня была та же проблема с Ctrl + Z и Ctrl + Y , включая соответствующий xev-вывод с «событием KeymApNotify» .
Решение состоит в следующем: назначьте новое сочетание клавиш именно таким комбинациям с xfce4-keyboard-settings и удалите их после этого. После этого снова работали Ctrl + Z (отменить) и Ctrl + Y (повторить) .
-121--54311- В качестве решения оболочки getopts
, вероятно, проще всего. Суть getopts
заключается в том, что POSIX-specified делать именно то, что вы просите - обрабатывать поток байтов в оболочечном цикле. Я знаю, это звучит странно, потому что, если вы похожи на меня до того, как я узнал это, вы, вероятно, думаете, ну, боже, я думал, что это должно было работать с переключателями командной строки. Что верно, но это тоже первое. Подумайте:
-thisisonelongstringconsistingofseparatecommandlineswitches
Да, getopts
должен справиться с этим. Он должен разделить этот символ по символу в цикле и вернуть вам каждый символ в переменной оболочки $ OPTARG
или в другой, который вы указываете по имени все в зависимости от того, как конкретно вы получаете при его вызове. Более того, он должен возвращать ошибки в переменных оболочки и сохранять ход выполнения , когда это происходит в переменной оболочки $ OPTIND
, так что он может возобновиться справа там, где он остался , если вы можете как-то решить его. И он должен выполнять всю работу, не прибегая ни к одному подслому.
Допустим, у нас есть:
arg=$(seq -s '' 1000); set --
while getopts :0123456789 v -"${arg}"
do [ "$((i=$i+1<6?$i+1:0))" -gt 0 ] ||
set "$@" "$v"
done
Ммм... Интересно, сработало ли это?
echo "$((${#arg}/6))" "$#"
482 482
Это хорошо...
eval '
printf %.1s\\n "${arg#'"$(printf %0$((124*6-1))d | tr 0 \?)"'}" "${124}"'
4
4
Таким образом, как видно, команда getopts
полностью задает массив для каждого шестого байта в последовательность. И это не обязательно должны быть такие числа - и это даже не должны быть оболочечные символы - и вы даже не нужно указывать целевые символы, как я сделал это выше с 01234565789
тоже. Я неоднократно проверял это на множестве снарядов, и все они просто работают. Есть некоторые причуды - bash
отбросит первый символ, если это символ пробела - dash
принимает двоеточие :
в качестве заданного параметра, даже если речь идет только о специально запрещенном POSIX. Но ничего из этого не имеет значения, потому что getopts
по-прежнему депонирует текущее значение символа opt в $ OPTARG
, даже когда он возвращает вам ошибку (представленную как? назначается указанному параметру opt var) и в противном случае явно не используется $ OPTARG
, если только вы не объявили, что параметр должен иметь аргумент. А пробельная вещь вроде как хорошая - она отбрасывает только ведущее пространство, которое отлично, потому что, работая с неизвестными значениями, можно сделать:
getopts : o -" $unknown_value"
... разорвать петлю без какой-либо опасности того, что первый персонаж на самом деле окажется в ваших принятых аргах последовательности -что приведет к тому, что getopts
заедет всю вещь в $ OPTARG
сразу - в качестве аргумента.
Вот еще один пример:
OPTIND=1
while getopts : o -" $(dd if=/dev/urandom bs=16 count=1 2>/dev/null)"
do printf '\\%04o' "'$OPTARG"; done
\0040\0150\0071\0365\0320\0070\0161\0064\0274\0115\0012\0215\0222\0271\0146\0057\0166
Я установил $ OPTIND = 1
в первой строке, потому что я только что использовал getopts
и, пока вы не сбросите его, он ожидает, что его следующий вызов будет продолжаться там, где он остался - он хочет «$ {arg2}»
другими словами. Но я не хочу давать, и сейчас я делаю другую вещь, поэтому я сообщаю об этом, сбрасывая $ OPTIND
, на который точка хороша идти.
В этом я использовал zsh
- который не спорит о ведущем пространстве - и поэтому первый символ восьмеричный 40 - символ пространства. Я обычно не использую getopts
таким образом, хотя - я обычно использую его, чтобы избежать выполнения write ()
для каждого байта и вместо этого назначить его выход - который приходит в виде переменной - другой переменной оболочки - как я сделал это с помощью set
после моды. Затем, когда я готов, я могу взять всю последовательность и когда я обычно снимаю первый байт.
Следующая программа python должна делать то, что вы хотите, или что-то очень близкое к ней.
В required _ output.txt
3-я строка кажется ошибочной:
Mem _ id # -aa3: time- file1.txt value = ccx3/file2.txt value = dd3
dd3, вероятно, должен быть
cc3 '
Кроме того, что выходные данные программы совпадают, за исключением пробела, который кажется немного нерегулярным в выборке выходных данных.
Ввод рассматривается как упорядоченный по ключу (memid)
Ввод выборки немного ограничен ожидаемым поведением, когда первая и вторая строки имеют один и тот же мемид дважды (или более).
На выходе ()
я пытаюсь сопоставить
любые строки и все совпадающие строки (слева и справа). Поэтому порядок совпадения строк в пределах одного и того же мемида не важен. Если левое или правое или оба являются пустыми после печати легко (особенно когда оба пустые). В остальном я совпаду с каждой оставшейся строкой слева направо.
Вывод определяется fmt
последовательностей в line _ out ()
, можно свободно изменить/переупорядочить это.
#! /usr/bin/env python
# coding: utf-8
# http://unix.stackexchange.com/q/161913/33055
from __future__ import print_function
from collections import OrderedDict
from logging import debug
import sys
class RowBuffer:
def __init__(self, file_name, delim=None, max_diff=3):
"""delim is the character that is used for splitting input.
None->whitespace
"""
self._verbose = 0
self._file_name = file_name
self._fp = open(self._file_name)
self._delim = delim
self._max_diff = max_diff
self._head = self._fp.readline().split(delim)
# the buffer consists of a maximum of max_diff entries
# the keys are the first items of a row, the value a list
# of all other items on that row
self._buffer = OrderedDict()
self.fill_buffer()
def compare(self, rb):
"""check if self._buffer"""
if self._head != rb._head:
print('headings differ:\n {}\n {}'.format(
self._head, rb._head))
while self._buffer:
l = self.get()
try:
r = rb.get()
except KeyError:
debug('only left %s', l[0])
self.output(l, None, rb)
break
if l[0] == r[0]:
debug('compare vals %s', l[0])
self.output(l, r, rb)
continue
if l[0] in rb:
# left key in right, but not at top
# output right until top keys are same
while l[0] != r[0]:
debug('only right %s', r[0])
self.output(None, r, rb)
r = rb.get()
self.output(l, r, rb)
continue
if r[0] in self:
# right key in left, but not at top
# output left until top keys are same
while l[0] != r[0]:
debug('only left %s', l[0])
self.output(l, None, rb)
l = self.get()
self.output(l, r, rb)
continue
# neither found: output both
debug('neither left in right nor vv %s %s', l[0], r[0])
self.output(l, None, rb)
self.output(None, r, rb)
while rb._buffer: # remaining in right file
r = rb.get()
debug('only right %s', r[0])
self.output(None, r, rb)
def output(self, l, r, right):
fmt1 = '{col0_header}#-{col0_value} : {col_header}- ' \
'{left_file_name} value = {left_value} / ' \
'{right_file_name} value= {right_value}'
d = dict(
col0_header=self._head[0],
left_file_name=self._file_name,
right_file_name=right._file_name,
)
if l is not None and r is not None:
# one or more values on both sides, compare all lines on the
# left with all on the right remove any matching pairs
match = {} # left index to right index
for lidx, lv in enumerate(l[1]):
for ridx, rv in enumerate(r[1]):
if lv == rv:
if lidx not in match:
match[lidx] = ridx
# pop from back of list, not invalidate index
for lidx in sorted(match, reverse=True):
l[1].pop(lidx)
for ridx in sorted(match.values(), reverse=True):
r[1].pop(lidx)
if r is None or not r[1]:
for lv in l[1]:
for idx, k in enumerate(self._head[1:]):
self.line_out(d, col0_value=l[0], col_header=k,
left_value=lv[idx], right_value=' ')
return
if l is None or not l[1]:
for rv in r[1]:
for idx, k in enumerate(self._head[1:]):
self.line_out(d, col0_value=l[0], col_header=k,
left_value=' ', right_value=rv[idx])
return
# print non matching
for lv in l[1]:
for rv in r[1]:
for idx, k in enumerate(self._head[1:]):
if lv[idx] == rv[idx]:
continue # same value
self.line_out(d, col0_value=l[0], col_header=k,
left_value=lv[idx], right_value=rv[idx])
def line_out(self, d, **kw):
# manipulate and print output
# the fields of the format string can be arbitrarily arranged
# as long as the field names (between {} match)
fmt = '{col0_header}#-{col0_value} : {col_header}- ' \
'{left_file_name} value = {left_value} / ' \
'{right_file_name} value= {right_value}'
d1 = d.copy()
d1.update(kw)
s = fmt.format(**d1)
# s = s.rstrip()
s = s[0].upper() + s[1:] # sample output doesn't match input
print(s)
def get(self):
item = self._buffer.popitem(last=False)
self.fill_buffer()
return item
def fill_buffer(self):
if self._fp is None:
return
while len(self._buffer) < self._max_diff:
row = self._fp.readline().split(self._delim)
if not row:
self._fp.close()
self._fp = None
return
entry = self._buffer.setdefault(row[0], [])
entry.append(row[1:])
def __contains__(self, key):
self.fill_buffer()
return key in self._buffer
rb1 = RowBuffer(sys.argv[1])
rb2 = RowBuffer(sys.argv[2])
rb1.compare(rb2)