Преобразование библиографических ссылок для использования с Latex

Если я правильно понял, вы хотите проверить, имеет ли второй столбец определенный алфавит, если да, попробуйте ниже awkскрипт, который сообщит, какой из них существует с соответствующим количеством, а какой нет с "NOT FOUND!"замечание.

awk -v alphabet="$(printf "%s" {a..z})" 'BEGIN{ split(alphabet, arr, "") }
    { chrs[$2]++ } END{ for(y in chrs) for(x in arr)
        { if(arr[x] in chrs) {print y, chrs[y]; delete arr[x]; break }
            else{ print arr[x]" NOT FOUND!"; delete arr[x] }
        }
}' infile

Выход:

w 1
z 3
a 1
b 1
c 1
f NOT FOUND!
g NOT FOUND!
h NOT FOUND!
i NOT FOUND!
j NOT FOUND!
k NOT FOUND!
l NOT FOUND!
m NOT FOUND!
n NOT FOUND!
o NOT FOUND!
p NOT FOUND!
q NOT FOUND!
r NOT FOUND!
s NOT FOUND!
t NOT FOUND!
u NOT FOUND!
v NOT FOUND!
d 1
x NOT FOUND!
y NOT FOUND!
e 1
4
13.02.2020, 12:02
1 ответ

Следующая awkпрограмма должна работать. Он ищет (... )элементов в каждой строке и проверяет, соответствуют ли они «автор (с ), год» или «автор (с )1 год1, автор (с )2 год2,..." узор. Если да, то создается команда цитирования и заменяется группа (... ); в противном случае он оставляет группу как есть.

#!/usr/bin/awk -f


# This small function creates an 'authorYYYY'-style string from
# separate author and year fields. We split the "author" field
# additionally at each space in order to strip leading/trailing
# whitespace and further authors.
function contract(author, year)
{
    split(author,auth_fields," ");
    auth=tolower(auth_fields[1]);
    return sprintf("%s%4d",auth,year);
}



# This function checks if two strings correspond to "author name(s)" and
# "year", respectively.
function check_entry(string1, string2)
{
    if (string1 ~ /^ *([[:alpha:].-]+ *)+$/ && string2 ~ /^ *[[:digit:]]{4} *$/) return 1;
    return 0;
}




# This function creates a 'citation' command from a raw element. If the
# raw element does not conform to the reference syntax of 'author, year' or
# 'author1 year1,author2 year2,...', we should leave it "as is", and return
# a "0" as indicator.
function create_cite(raw_elem)
{
    cite_argument=""

    # Split at ','. The single elements are either name(list) and year,
    # or space-separated name(list)-year statements.
    n_fields=split(raw_elem,sgl_elem,",");

    if (n_fields == 2 && check_entry(sgl_elem[1],sgl_elem[2]))
    {
        cite_argument=contract(sgl_elem[1],sgl_elem[2]);
    }
    else
    {
        for (k=1; k<=n_fields; k++)
        {
            n_subfield=split(sgl_elem[k],subfield," ");

            if (check_entry(subfield[1],subfield[n_subfield]))
            {
                new_elem=contract(subfield[1],subfield[n_subfield]);
                if (cite_argument == "")
                {
                    cite_argument=new_elem;
                }
                else
                {
                    cite_argument=sprintf("%s,%s",cite_argument,new_elem);
                }
            }
            else
            {
                return 0;
            }
        }
    }


    cite=sprintf("\\{%s}",cite_argument);
    return cite;
}




# Actual program
# For each line, create a "working copy" so we can replace '(...)' pairs
# already processed with different text (here: 'X... Y'); otherwise 'sub'
# would always stumble across the same opening parentheses.
# For each '(... )' found, check if it fits the pattern. If so, we replace
# it with a 'cite' command; otherwise we leave it as it is.

{
    working_copy=$0;

    # Allow for unmatched ')' at the beginning of the line:
    # if a ')' was found before the first '(', mark is as processed
    i=index(working_copy,"(");
    j=index(working_copy,")");
    if (i>0 && j>0 && j<i) sub(/\)/,"Y",working_copy);

    while (i=index(working_copy,"("))
    {
        sub(/\(/,"X",working_copy); # mark this '(' as "already processed

        j=index(working_copy,")");
        if (!j)
        {
            continue;
        }
        sub(/\)/,"Y",working_copy); # mark this ')', too


        elem=substr(working_copy,i+1,j-i-1);

        replacement=create_cite(elem);
        if (replacement != "0")
        {
            elem="\\(" elem "\\)"
            sub(elem,replacement);
        }

    }
    print $0;
}

Вызовите программу с помощью

~$ awk -f transform_citation.awk input.tex

Обратите внимание , что программа ожидает, что ввод будет "достаточно" правильно -сформирован, т. е. все скобки в строке должны быть совпадающими парами (, хотя одна закрывающая скобка в начале строки разрешена для, а несовпадающие открывающие круглые скобки будут игнорироваться ).

Заметьте также , что некоторые из синтаксиса выше требуют GNU awk. Чтобы быть переносимым на другие реализации, замените

if (string1 ~ /^ *([[:alpha:].-]+ *)+$/ && string2 ~ /^ *[[:digit:]]{4} *$/) return 1;

с

if (string1 ~ /^ *([a-zA-Z.-]+ *)+$/ && string2 ~ /^ *[0123456789][0123456789][0123456789][0123456789] *$/) return 1;

и убедитесь, что вы установили языковой стандарт сортировки на C.

5
28.04.2021, 23:24

Теги

Похожие вопросы