Sök…


Introduktion

Den cut kommando är ett snabbt sätt att extrahera delar av rader av textfiler. Det tillhör de äldsta Unix-kommandona. De mest populära implementeringarna är GNU-versionen som finns på Linux och FreeBSD-versionen som finns på MacOS, men varje smak av Unix har sin egen. Se nedan för skillnader. Inmatningsraderna läses antingen från stdin eller från filer som listas som argument på kommandoraden.

Syntax

  • klipp -f1,3 # extrakt första och tredje flikavgränsade fält (från stdin)

  • klipp -f1-3 # extrakt från första upp till tredje fält (slutar ingår)

  • klipp -f-3 # -3 tolkas som 1-3

  • cut -f2- # 2- tolkas som från den andra till den sista

  • skär -c1-5,10 # extrakt från stdin karaktärerna i positionerna 1,2,3,4,5,10

  • cut -s -f1 # undertryck rader som inte innehåller avgränsare

  • klipp - komplement -f3 # (endast GNU-klipp) extrahera alla fält utom det tredje

parametrar

Parameter detaljer
-f, - fält Fältbaserat urval
-d, - avgränsare Avgränsare för fältbaserat urval
-c, - tecken Teckenbaserat urval, ignorerad avgränsare eller fel
-s, - bara avgränsad Undertryck rader utan tecken för avgränsning (skrivs ut som annars)
--komplement Inverterat val (extrahera alla utom angivna fält / tecken
--output-avgränsare Ange när det måste skilja sig från ingångsavgränsaren

Anmärkningar

1. Syntaxskillnader

Långa alternativ i tabellen ovan stöds endast av GNU-versionen.

2. Ingen karaktär får specialbehandling

FreeBSD- cut (som till exempel levereras med MacOS) har inte --complement , och när det gäller colrm istället använda colrm kommandot:

  $ cut --complement -c3-5 <<<"123456789"
  126789

  $ colrm 3 5 <<<"123456789"
  126789

Det finns emellertid en stor skillnad, eftersom colrm behandlar TAB-tecken (ASCII 9) som verkliga tabeller upp till nästa multipel av åtta, och bakutrymmen (ASCII 8) som -1 breda; tvärtom, cut behandlar alla tecken som en kolumn bred.

  $ colrm  3 8 <<<$'12\tABCDEF' # Input string has an embedded TAB
  12ABCDEF

  $ cut --complement -c3-8 <<<$'12\tABCDEF'
  12F

3. (Fortfarande nej) Internationalisering

När cut utformades var alla karaktärer en byte lång och internationalisering var inte ett problem. När skrivsystem med bredare tecken blev populära var lösningen som antogs av POSIX att skilja mellan den gamla -c omkopplaren, som borde behålla sin betydelse att välja tecken, oavsett hur många byte breda, och att införa en ny switch -b som borde välj byte, oavsett aktuell teckenkodning. I de mest populära implementeringarna introducerades och fungerar -b , men -c fungerar fortfarande exakt som -b och inte som det borde. Till exempel med GNU- cut :

Det verkar som om SE: s spamfilter svartlistor engelska texter med isolerade kanji-tecken i dem. Jag kunde inte övervinna denna begränsning, så följande exempel är mindre uttrycksfulla än de kunde vara.

  # In an encoding where each character in the input string is three bytes wide,
  # Selecting bytes 1-6 yields the first two characters (correct)
  $ LC_ALL=ja_JP.UTF-8 cut -b1-6 kanji.utf-8.txt
  ...first two characters of each line...
  

  # Selecting all three characters with the -c switch doesn’t work.
  # It behaves like -b, contrary to documentation.
  $ LC_ALL=ja_JP.UTF-8 cut -c1-3 kanji.utf-8.txt
  ...first character of each line...

  # In this case, an illegal UTF-8 string is produced.
  # The -n switch would prevent this, if implemented.
  $ LC_ALL=ja_JP.UTF-8 cut -n -c2 kanji.utf-8.txt
  ...second byte, which is an illegal UTF-8 sequence...

Om dina karaktärer ligger utanför ASCII-intervallet och du vill använda cut , bör du alltid vara medveten om teckenbredden i din kodning och använda -b . Om och när -c börjar fungera som dokumenterat behöver du inte ändra dina skript.

4. Hastighetsjämförelser

cut begränsningar gör att människor tvivlar på dess användbarhet. Faktum är att samma funktionalitet kan uppnås med kraftfullare och mer populära verktyg. Men cut är 's fördel dess prestanda. Se nedan för några hastighetsjämförelser. test.txt har tre miljoner rader, med fem rymdseparerade fält vardera. För awk testet användes mawk eftersom det är snabbare än GNU awk . Själva skalet (sista raden) är den överlägset värsta utövaren. Tiderna (i sekunder) är vad time kommandot ger som realtid.

(Bara för att undvika missförstånd: alla testade kommandon gav samma utgång med den givna ingången, men de är naturligtvis inte likvärdiga och skulle ge olika utgångar i olika situationer, särskilt om fälten avgränsades av ett variabelt antal utrymmen)

Kommando Tid
cut -d ' ' -f1,2 test.txt 1.138s
awk '{print $1 $2}' test.txt 1.688s
join -a1 -o1.1,1.2 test.txt /dev/null 1.767s
perl -lane 'print "@F[1,2]"' test.txt 11.390s
grep -o '^\([^ ]*\) \([^ ]*\)' test.txt 22.925s
sed -e 's/^\([^ ]*\) \([^ ]*\).*$/\1 \2/' test.txt 52.122s
while read ab _; do echo $a $b; done <test.txt 55.582s

5. Referens man sidor

Grundläggande användning

Den typiska användningen är med filer av CSV-typ, där varje rad består av fält separerade med en avgränsare, specificerad av alternativet -d . Standardavgränsaren är TAB-tecknet. Anta att du har en datafil data.txt med rader som

0 0 755 1482941948.8024
102 33 4755 1240562224.3205
1003 1 644 1219943831.2367

Sedan

# extract the third space-delimited field
$ cut -d ' ' -f3 data.txt
755
4755
644

# extract the second dot-delimited field
$ cut -d. -f2 data.txt    
8024
3205
2367

# extract the character range from the 20th through the 25th character
$ cut -c20-25 data.txt 
948.80
056222    
943831

Som vanligt kan det finnas valfria mellanrum mellan en switch och dess parameter: -d, är samma som -d ,

GNU- cut gör det möjligt att specificera ett --output-delimiter : (en oberoende funktion i detta exempel är att en semikolon som ingångsavgränsare måste undkommas för att undvika dess speciella behandling av skalet)

$ cut --output-delimiter=, -d\; -f1,2 <<<"a;b;c;d"
a,b

Endast en avgränsande karaktär

Du kan inte ha mer än en avgränsare: om du anger något som -d ",;:" kommer vissa implementationer bara att använda det första tecknet som en avgränsare (i detta fall komma.) Andra implementationer (t.ex. GNU- cut ) kommer att ge du ett felmeddelande.

$ cut -d ",;:" -f2 <<<"J.Smith,1 Main Road,cell:1234567890;land:4081234567"
cut: the delimiter must be a single character
Try `cut --help' for more information.

Upprepade avgränsare tolkas som tomma fält

$ cut -d, -f1,3 <<<"a,,b,c,d,e"
a,b

är ganska uppenbart, men med rumsavgränsade strängar kan det vara mindre uppenbart för vissa

$ cut -d ' ' -f1,3 <<<"a  b c d e"
a b

cut kan inte användas för att analysera argument som skalet och andra program gör.

Ingen offert

Det finns inget sätt att skydda avgränsaren. Kalkylark och liknande CSV-hanteringsprogramvara kan vanligtvis känna igen ett textcitationstecken som gör det möjligt att definiera strängar som innehåller en avgränsare. Med cut du inte.

$ cut -d, -f3 <<<'John,Smith,"1, Main Street"'
"1

Extrahera, inte manipulera

Du kan bara extrahera delar av rader, inte ordna om eller upprepa fält.

$ cut -d, -f2,1 <<<'John,Smith,USA' ## Just like -f1,2
John,Smith
$ cut -d, -f2,2 <<<'John,Smith,USA' ## Just like -f2
Smith


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow