Проблема может быть решена путем фильтрации вывода diff
. Этот пример подходит мне (хотя размещение и размер желоба между левой и правой сторонами вывода diff, вероятно, будут деталями, которые различаются между реализациями):
#!/bin/sh
# $Id: diff-two-column,v 1.2 2016/09/26 20:38:32 tom Exp $
# see http://unix.stackexchange.com/questions/312025/how-to-associate-line-number-from-a-file-to-the-side-by-side-diff-output-result
usage() {
cat >&2 <<EOF
usage: $0 file1 file2
EOF
exit 1
}
[ $# = 2 ] || usage
[ -f "$1" ] || usage
[ -f "$2" ] || usage
width=${COLUMNS:-80}
check=$(stty size|cut -d' ' -f2)
[ -n "$check" ] && width=$check
diff -W $width -y "$1" "$2" | \
expand | \
awk -v width=$width '
BEGIN {
L=0;
R=0;
gutter = width / 2;
half = gutter - 2;
}
{
textL = substr($0, 1, half - 1);
sub("[ ]+$", "", textL); # trim trailing blanks
# The script relies on correctly extracting textM, the gutter:
# if lines differ, textM is " ! "
# if line inserted, textM is " > "
# if line deleted, textM is " < "
# if lines unchanged, textM is " "
textM = substr($0, gutter - 2, 3);
textR = ( length($0) > gutter ) ? substr($0, gutter+1, half) : "";
if ( textM != " > " ) {
L++;
}
if ( textM != " < " ) {
R++;
}
if ( textL != textR ) {
# printf "SHOW %s\n", $0;
# printf "gap \"%s\"\n", textM;
# printf "<<< \"%s\"\n", textL;
# printf ">>> \"%s\"\n", textR;
if ( textL == "" ) {
printf "%5s %-*s %-3s %5d %s\n",
" ", half, textL,
textM,
R, textR;
} else if ( textR == "" ) {
printf "%5d %-*s %-3s %5s %s\n",
L, half, textL,
textM,
" ", textR;
} else {
printf "%5d %-*s %-3s %5d %s\n",
L, half, textL,
textM,
R, textR;
}
} else {
# printf "SKIP %s\n", $0;
}
}
'
Вы не можете добавлять номера строк до diff
, потому что, если есть вставки или удаления, номера строк, начинающиеся с этой точки, не будут совпадать, что делает различия бесполезными. Мой сценарий вычисляет номера строк для левой и правой сторон разницы в сценарии awk:
awk
, это $ 0
) левую ( textL
) и правую ( textR
) строк и проверяет, пусты ли они (что произошло бы, если бы была вставка / удаление). diff
, но добавляет номера строк. Учитывая, что это слева
1
2
3
4
This is line A
6
This is line C
123456789.123456789.123456789.123456789.123456789.
yyy
и это справа
1
2
3
4
This is line B
6
This is line D
abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.
xxx
(10 строк слева, 9 справа), этот сценарий выдаст
5 This is line A | 5 This is line B
7 This is line C | 7 This is line D
8 123456789.123456789.123456789.1234567 | 8 abcdefghi.abcdefghi.abcdefghi.abcdefg
| 9 xxx
10 yyy <
Это будет работать даже без цикла для всех имен файлов, начинающихся с file
:
perl -pe 's/\n/ /g' file*
Для таких операций я предпочитаю perl. Имеет тот же синтаксис, что и sed , является переносимым и не имеет всех этих странных параметров sed .
Вы также можете применить переключатель -i
к perl (например, sed), чтобы внести изменения на месте: perl -i.old -pe ....
(старый файл будет скопирован с расширением .old -Вы можете просто использовать -i
и файл резервной копии не будет сохранен)
Если вы предпочитаете, вы можете использовать команду find
следующим образом:
$ find . -type f -name 'file*' -exec bash -c 'tr "\n" " " <$0 >$0.new' {} \;
perl -i -lpe '$\=$"' file.data
-i
включает редактирование на месте. -l
устанавливает ORS = RS = "\n"
-p
устанавливает неявное чтение входного файла + автоматическую печать записей. $\
— это ORS
, для которого установлено значение $" = OFS = пробел по умолчанию
. Это команда sed
, которую вы ищете:
find /directory/. -type f -exec sed -i ':begin;$!N;s/\n/ /;tbegin' {} \;