Jak przeplatać linie dwóch lub więcej plików?

10

Próbowałem uzyskać 2 pliki wyjściowe w jednym pliku. Próbowałem poniżej polecenia:

cat file1 file2

ale tutaj file2dołącza się dane file1.

Potrzebuję file1pierwszej linii, a następnie file2pierwszej linii i file1drugiej linii, a następnie file2drugiej linii itp.

Czy ktoś może mi powiedzieć, jak to zrobić w prosty sposób?

użytkownik73553
źródło

Odpowiedzi:

17

Jest na to aplikacja!

$ cat file1
file1 line1
file1 line2

$ cat file2
file2 line1
file2 line2

Teraz, jeśli przekażesz te pliki jako argumenty do paste:

$ paste -d' ' file1 file2
file1 line1 file2 line1
file1 line2 file2 line2

Jeśli przez „plik1 pierwsza linia, po której następuje plik2 pierwsza linia, i plik1 druga linia, a następnie plik2 druga linia itp.”, Oznacza to, że chcesz wstawić nową linię między każdą linią, po prostu dostosuj -dopcję (separator).

$ paste -d'\n' file1 file2
file1 line1
file2 line1
file1 line2
file2 line2
terdon
źródło
2

POSIX Awk; działa to z dowolną ilością plików, a pliki nie muszą nawet mieć takiej samej liczby linii. Skrypt działa tak długo, aż wszystkie pliki znajdą się poza liniami:

BEGIN {
  do {
    br = ch = 0
    while (++ch < ARGC)
      if (getline < ARGV[ch]) {
        printf ch < ARGC - 1 ? $0 FS : $0 RS
        br = 1
      }
  } while (br)
}
Steven Penny
źródło
Jest z tym jeden problem, jeśli dane wejściowe zawierają znaki „%”, próbował je sprawdzić w printf. Moja aktualizacja byłaby (nie jestem pewna, czy to jest całkowicie poprawne):printf "%s", ((ch < ARGC - 1) ? $0 FS : $0 RS)
Scala William
0

Szybkie rozwiązanie bash

# Takes as many file arguments as needed
function InterleaveFiles {

    local counter=0
    local hasLine=true

    while [ $hasLine == true ]; do
            hasLine=false
            for i in "$@"; do
                    line=$(awk 'NR == num_line {print; exit}' num_line=$((counter+1)) "$i")
                    if [ -n "$line" ]; then
                            echo "$line"
                    hasLine=true
                    fi
            done
            counter=$((counter+1))
    done
}

InterleaveFiles plik1 plik2 plik3 plik4

Orsiris de Jong
źródło
-2
paste -d '\n' file1 file2 > file3

gdzie file1i file2są plikami wejściowymi i file3będą utworzonymi danymi wyjściowymi.

Prateek Singh
źródło
1
Witamy na Giełdzie Stosów U&L! Ta odpowiedź jest prawie identyczna z odpowiedzią Terdona . W przypadkach, w których uważasz, że możesz poprawić odpowiedź, ale nie podajesz zasadniczo nowych informacji, rozważ zaproponowanie edycji istniejącej odpowiedzi . Odpowiedzi są również porządkowane na podstawie głosowania, więc każda odpowiedź powinna być samodzielna lub odnosić się do innej odpowiedzi. Dlatego onelinerom powłoki powinien towarzyszyć opis wyjaśniający ich działanie.
Thomas Nyman