Sformatuj wyjście xargs

10

Chciałbym zmienić format wyjściowych wyświetlaczy xargs

cat k.txt 
1 
2 
3 

I

cat k.txt | xargs 
1 2 3

Jednak chciałbym mieć 1, 2, 3lub 1|2|3. Jakieś sugestie?

Avinash
źródło
Że można osiągnąć coś (nie dokładnie tego) jak xargs cat -n, ale jest łatwiejsze, jeśli tylko przyciąć znaki nowej linii, to można osiągnąć echo $(cat), greplub awk(kraul drodze to zrobić). xargsnie pasują dobrze do twojego obecnego celu.
41754,

Odpowiedzi:

18

Poniżej znajduje się kilkanaście przykładów, w jaki sposób możesz pobrać taki plik:

$ cat k.txt
1
2
3

i przekonwertuj go na ten format:

1,2,3

Możesz użyć tego polecenia, aby utworzyć powyższy plik, jeśli chcesz grać razem:

$ cat <<EOF > k.txt
1
2
3
EOF

Poniższe przykłady są podzielone na 2 grupy. Te, które „pracują” i te, które „prawie” działają. Opuszczam je, ponieważ często jest tak samo cenne, aby zobaczyć, dlaczego coś nie działa, jak i zobaczyć, dlaczego coś działa.

Większość znanych mi języków skryptowych jest reprezentowanych. Niektóre są reprezentowane wiele razy, ponieważ podobnie jak w przypadku słynnego akronimu, do którego zwykle odwołuje się Perl, TIMTOWTDI .

UWAGA: Możesz zamienić przecinek ( ,) w poniższych przykładach i zastąpić go dowolnymi znakami, np |.

Przykłady, które „działają”

Te fragmenty kodu wygenerują pożądany wynik.

pastePolecenie:

$ paste -s -d ',' k.txt 
1,2,3

sedPolecenie:

$ sed ':a;N;$!ba;s/\n/,/g' k.txt
1,2,3

$ sed ':a;{N;s/\n/,/};ba' k.txt 
1,2,3

perlPolecenie:

$ perl -00 -p -e 's/\n(?!$)/,/g' k.txt
1,2,3

$ perl -00 -p -e 'chomp;tr/\n/,/' k.txt
1,2,3

awkPolecenie:

$ awk '{printf"%s%s",c,$0;c=","}' k.txt
1,2,3

$ awk '{printf "%s,",$0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk -vORS=, 1 k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk 'BEGIN {RS="dn"}{gsub("\n",",");print $0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

pythonPolecenie:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,3

$ python -c "import sys; print sys.stdin.read().replace('\n', ',').rstrip(',')" <k.txt
1,2,3

mapfileWbudowane Bash :

$ mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
1,2,3

rubyPolecenie:

$ ruby -00 -pe 'gsub /\n/,",";chop' < k.txt
1,2,3

$ ruby -00 -pe '$_.chomp!"\n";$_.tr!"\n",","' k.txt
1,2,3

phpPolecenie:

$ php -r 'echo strtr(chop(file_get_contents($argv[1])),"\n",",");' k.txt
1,2,3

Ostrzeżenia

Większość powyższych przykładów będzie działać dobrze. Niektóre mają ukryte problemy, takie jak powyższy przykład PHP. Funkcja chop()jest właściwie aliasem do rtrim(), więc końcowe spacje ostatniego wiersza również zostaną usunięte.

Podobnie jest z pierwszym przykładem Rubiego i pierwszym przykładem Pythona. Problem polega na tym, że wszyscy wykorzystują rodzaj operacji, która zasadniczo „odcina”, ślepo, końcową postać. Jest to dobre na przykład w przypadku dostarczonego przez PO, ale należy zachować ostrożność podczas korzystania z tych typów jednego wkładki, aby upewnić się, że są one zgodne z przetwarzanymi danymi.

Przykład

Powiedz nasz przykładowy plik, k.txtwyglądał tak:

$ echo -en "1\n2\n3" > k.txt

Wygląda podobnie, ale ma jedną niewielką różnicę. Nie ma końcowego znaku nowej linii ( \n) jak oryginalny plik. Teraz, gdy uruchamiamy pierwszy przykład w języku Python, otrzymujemy:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,

Przykłady, które „prawie” działają

Oto przykłady „zawsze druhny, nigdy nie panny młodej” . Większość z nich prawdopodobnie można by zaadaptować, ale gdy pracuje się nad potencjalnym rozwiązaniem problemu, kiedy wydaje się on „zmuszony”, jest to prawdopodobnie nieodpowiednie narzędzie do pracy!

perlPolecenie:

$ perl -p -e 's/\n/,/' k.txt
1,2,3,

trPolecenie:

$ tr '\n' ','  < k.txt 
1,2,3,

W cat+ echokomendy:

$ echo $(cat k.txt)
1 2 3

rubyPolecenie:

$ ruby -pe '$_["\n"]=","' k.txt
1,2,3,

Wbudowane Bash while+ read:

$ while read line; do echo -n "$line,"; done < k.txt
1,2,3,
slm
źródło
1
Jeśli chodzi o awkwolę krótszą alternatywę:awk -vORS=, 1 k.txt
manatwork
Nie jestem pewien, czy CentOS ma bash:mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
manatwork
nie jestem pewien co do nowej linii końcowej. Według mojego testu twój perli pierwszy awkteż je mają.
manatwork
Postawiłbym ten pastena górze. Właśnie po to paste -stu jest. To standardowe polecenie i byłoby najbardziej wydajne. Wszystkie pozostałe mają nadmiar umiejętności i / lub nie są przenośne lub mają ograniczenia.
Stéphane Chazelas
mapfilejest stosunkowo nowy, dodany w wersji bash4.0.
manatwork
4

@slm już miło odpowiedział, ale jako pytanie „sformatuj wyjście xargs”

xargs -I{} echo -n "{}|" < test.txt
  • -I jest opcja „zamień ciągi”.
  • {} jest symbolem zastępczym dla tekstu wyjściowego.
  • Jest to podobne do użycia pary nawiasów klamrowych w „find”.

Jeśli chcesz pozbyć się trailingu |, możesz sedzrobić porządki:

$ xargs -I{} echo -n "{}|" < k.txt  | sed -e 's/|$//'
1|2|3
Rahul Patil
źródło
To dodaje dodatkową fajkę po 3. „1 | 2 | 3 |”. Mam ten sam problem z rozwiązaniem pętli while i awk.
slm
tak, jeśli pojawi się nowa linia .. tr, seda także inne ...
Rahul Patil
2

To jest stary wątek, wiem. OP poprosił o taki prosty kod. Aby utrzymać go blisko oryginału, mam proste rozwiązanie.

cat k.txt | xargs
1 2 3

użyj sed

cat k.txt | xargs | sed 's/ /,/g'
1,2,3

lub

cat k.txt | xargs | sed 's/ /|/g'
1|2|3

sed może wyglądać trochę dziwnie, ale zepsuty, ma to sens.

zastępuje. g 'jest globalne: bez tego spowoduje tylko pierwsze podstawienie w każdej nowej linii. Ponieważ używasz „xargs”, wyświetla je jako jeden wiersz. Otrzymasz więc „1,2 3”.

Separator służy do separacji. Użyłem znaku /. Jedna interesująca sztuczka: możesz zastąpić separator większością dowolnych innych znaków, o ile zachowamy ten sam format między cudzysłowami. To zadziałałoby również ....

cat k.txt | xargs | sed 's# #,#g'

lub

cat k.txt | xargs | sed 'sT T,Tg'

Oczywiście używanie pewnych znaków jako separatora może być mylące, więc bądź mądry.

Michael Bruce
źródło
0
xargs <k.txt | tr \  \|

Nie trzeba cat- wystarczy przejść na wejściu plików i - jeśli nie podano innego polecenia - xargsprzejdzie na jego domyślnego formatu - który jest w rodzaju z /bin/echo„s (bez interpretacji backslash c-escape) .

xargsusunie białe znaki z głowy / ogona z pliku wejściowego i wyciśnie inne sekwencje białych znaków do pojedynczej spacji. Oznacza to, że podczas przechodzenia z pliku trdo xargstakich jak:

tr \\n \| <k.txt | xargs

... drukuje ...

1|2|3|

... idzie w drugą stronę i działa tylko na argumentach, które xargsograniczają spacje ...

1|2|3\n

... ponieważ xargsdrukuje ostatni znak nowej linii (wymagany w przypadku pliku tekstowego) , ale nie uzyskuje w trten sposób odpowiedzi.

Należy jednak pamiętać, że to (lub inne oferowane tutaj rozwiązanie) nie uwzględnia xargscytowania w danych wejściowych. xargspoda dosłownie pojedyncze / podwójne / odwrócone ukośniki znaki spacji w nowej linii, które same mogą być cytowane w następujący sposób:

xargs <<\IN
1    2'      3'\'      \'4
IN

1 2      3' '4
mikeserv
źródło