Jak selektywnie skopiować szczegóły z pliku i wkleić je do nowego pliku?

11

Mam plik zawierający moje dane osobowe (.txt). Jak mogę za pośrednictwem terminalu skopiować tylko kilka szczegółów z pliku i umieścić je w nowym .txtpliku?

Na przykład, jeśli jest to zawartość pliku:

name : farah age : 23 phone number : 0123 education : degree

jak mogę skopiować tylko wiek i numer telefonu i wysłać je do nowego .txtpliku?

MsWanie
źródło
2
To zależy od tego, co chcesz skopiować do nowego pliku. Czy chcesz kilka pierwszych linii, kilka ostatnich, linie zawierające łańcuch, nie zawierające łańcucha, linie między dwoma łańcuchami? Istnieją narzędzia do wykonania tych wszystkich czynności, ale musimy wiedzieć, co chcesz zrobić.
Arcege

Odpowiedzi:

7

Można to zrobić na kilka sposobów. Jeśli twój plik ma jakąś znaną strukturę, możesz użyć grep. Do grepwyszukiwania poleceń pliku dla określonego wyrażenia i zwroty liniach pasujących do tego wyrażenia. Więc jeśli twój plik wygląda

Imię: Sally

Data urodzenia: 7.31.76

Adres: 1234 Main St.

SSN: 123–45–6789

możesz biec, grep Name info.txta on wróci Name: Sally. Następnie możesz przekierować dane wyjściowe do innego pliku. Więc dzwonię

grep Name info.txt > info2.txt

wypisze linię do nowego pliku info2.txt. Jeśli chcesz dodać nowe linie, możesz to zrobić

grep Address info.txt >> info2.txt

w przeciwnym razie plik zostanie zastąpiony.

Możesz także nauczyć się korzystać z edytora tekstu wiersza poleceń, takiego jak vim.

Kris Harper
źródło
2

Możesz użyć grep, aby wyszukać wyrażenie regularne w pliku details.txt i przekierować wynik do nowego pliku.

Jeśli wszystkie wiersze, które chcesz skopiować, mają coś wspólnego, innych wierszy nie możesz użyć:

grep "string in common" details.txt > new.txt

Jeśli nie trzeba będzie szukać dla każdego wiersza, który chcesz skopiować, wciąż przy grep, i dołączyć je do new.txt korzystania >>w zastępstwie >.

Danjjl
źródło
1

Istnieją również edytory, które działają w terminalu, np. Nano, vi i emacs.

Jeśli korzystasz z graficznego interfejsu użytkownika na komputerze lokalnym i terminalu na komputerze zdalnym, możesz także użyć myszy do kopiowania i wklejania z jednego okna / karty terminala do drugiego.

Elmicha
źródło
1

Zakładając, że plik wejściowy details.txtzawiera:

name: farah
age: 23
phone number: 0123
education: degree

możesz wybrać linie „nazwa” i „telefon” przez rozszerzone grep i przekierować wyjście do new.txt:

grep -E "age:|phone number:" details.txt > new.txt

Spowoduje to utworzenie pliku new.txt z:

age: 23
phone number: 0123

Jak to działa:

Grep drukuje tylko dopasowane linie. Te -Eopcje włączone rozszerzonego regexp, który daje możliwość skorzystania |(alternatywa). Pamiętaj, aby zacytować cały wzór, więc |zostanie zinterpretowany przez grep. W przeciwnym razie powłoka spróbuje zinterpretować. Nie chcesz tego tutaj.

Michał Šrajer
źródło
1

Pokazany plik ma wszystkie szczegóły w jednym wierszu:

name : farah age : 23 phone number : 0123 education : degree

Założyłem, że możesz na stałe wpisać kod age :do polecenia itp., Ale następujący po nim tekst będzie się różnił, a szczegóły mogą nie być w podanej kolejności lub być ciągłe.

Można wyodrębnić części linii z grep„s -oflagi. Drukuje tylko dopasowaną część, a nie całą linię.

Jeśli chcesz dołączyć części age :i phone number :, możesz użyć -eflagi, aby określić wiele dopasowań lub naprzemiennie.

$ grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file
age : 23
phone number : 0123

Wyrażenie [^ ]*oznacza dowolną liczbę znaków, które nie są spacjami, więc dopasowuje znaki po age :maksymalnie spacji.

Zamień filena nazwę pliku zawierającego twoje dane. Możesz zapisać nowy plik, przekierowując dane wyjściowe do nowego pliku za pomocą >operatora, w następujący sposób:

grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file > outfile

Gdy to zrobisz, nie zobaczysz żadnych wyników. Najpierw sprawdź dane wyjściowe, a następnie dodaj przekierowanie.

Oto przykład z naprzemiennością. Używamy -Eflagi, aby powiedzieć grepo rozszerzonym wyrażeniu regularnym. Składnia jest (pattern1|pattern2)taka - pasuje pattern1i / lub pattern2. Jeśli którykolwiek zostanie znaleziony, zostanie wydrukowany (niezależnie od tego, czy drugi zostanie znaleziony, czy nie). Teraz używam +znaczenia co najmniej jednego z poprzedzających znaków, zamiast *oznaczać zero lub więcej poprzedzających znaków. W tym kontekście oba działają równie dobrze.

$ grep -Eo '(age : [^ ]+|phone number : [^ ]+)' file
age : 23 
phone number : 0123 

Jeśli chcesz pominąć części age :i phone number:, możesz użyć -Pflagi, aby poprosić grepo użycie wyrażeń regularnych zgodnych z Perl. Obsługuje to naprzemienność, a także sposób dopasowywania tekstu po danym wzorcu:

$ grep -Po '(age : \K[^ ]+|phone number : \K[^ ]+)' file
23
0123

Jeśli chcesz sformatować tekst inaczej, możesz użyć sedna przykład:

$ sed -r 's/.*(age) : ([^ ]*).*(phone number) : ([^ ]*).*/\1:\2 | \3:\4/' file
age:23 | phone number:0123

To zależy od tego, czy agenadejdzie wcześniej phone number, więc dostosuj odpowiednio, jeśli tak nie jest. Jeśli nie możesz polegać na zamówieniu, możesz użyć tego bardzo skomplikowanego polecenia:

$ sed -r 's/(.*)(phone number : [^ ]+)(.*) .*/\2 \1\4/; s/(phone number) : ([^ ]+) .*(age) : ([^ ]+).*/\1: \2 | \3: \4/' file
phone number: 0123 | age: 23

To phone number :zmienia kolejność linii, tak aby sekcja była pierwsza na każdej linii, a następnie dokonuje drugiej zamiany, aby wybrać pożądane szczegóły. Technikę zastosowaną tutaj zawdzięczam Muru .

Uwagi na temat sedpoleceń nieobjętych poprzednimi objaśnieniami

  • -rużyj rozszerzonego wyrażenia regularnego dla bardziej czytelnych poleceń (GNU sedrozumie -Eto samo znaczenie)
  • s/old/new/wymienić oldznew
  • (pattern)zapisuje się w patterncelu późniejszego użycia, za pomocą \1lub \2etc (zgodnie z kolejnością od lewej do prawej, w której występują grupy przechwytywania - zwróć uwagę, że sedpomieści tylko 7 z nich!).
  • .dowolny znak, dlatego .*reprezentuje dowolną liczbę dowolnych znaków.
  • ; rozdziela polecenia, jak w powłoce.
Zanna
źródło