Zoeken…


Invoering

De opdracht cut is een snelle manier om delen van regels tekstbestanden te extraheren. Het hoort bij de oudste Unix-opdrachten. De meest populaire implementaties zijn de GNU-versie gevonden op Linux en de FreeBSD-versie gevonden op MacOS, maar elke smaak van Unix heeft zijn eigen. Zie hieronder voor verschillen. De invoerregels worden gelezen uit stdin of uit bestanden die als argumenten op de opdrachtregel worden vermeld.

Syntaxis

  • knippen -f1,3 # extract eerste en derde tabgescheiden veld (van stdin)

  • knippen -f1-3 # extract van eerste tot derde veld (uiteinden inbegrepen)

  • cut -f-3 # -3 wordt geïnterpreteerd als 1-3

  • cut -f2- # 2- wordt geïnterpreteerd vanaf de voorlaatste tot de laatste

  • knip -c1-5,10 # extract van stdin de karakters in posities 1,2,3,4,5,10

  • cut -s -f1 # onderdrukt lijnen die geen scheidingstekens bevatten

  • cut --complement -f3 # (alleen GNU cut) extraheer alle velden behalve de derde

parameters

Parameter Details
-f, --velden Veldgebaseerde selectie
-d, --delimiter Scheidingsteken voor veldgebaseerde selectie
-c, - tekens Op tekens gebaseerde selectie, scheidingsteken genegeerd of fout
-s, - alleen afgebakend Regels onderdrukken zonder scheidingstekens (anders afgedrukt)
--aanvulling Omgekeerde selectie (alles extraheren behalve opgegeven velden / tekens
--output-delimiter Geef op wanneer deze moet verschillen van het invoerbeperkingsteken

Opmerkingen

1. Syntaxisverschillen

Lange opties in de bovenstaande tabel worden alleen ondersteund door de GNU-versie.

2. Geen enkel personage krijgt een speciale behandeling

FreeBSD cut (die bijvoorbeeld wordt meegeleverd met MacOS) heeft niet de --complement schakelaar, en in het geval van colrm plaats daarvan de opdracht colrm gebruikt:

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

  $ colrm 3 5 <<<"123456789"
  126789

Er is echter een groot verschil, omdat colrm TAB-tekens (ASCII 9) behandelt als echte tabellen tot het volgende veelvoud van acht, en backspaces (ASCII 8) als -1 breed; integendeel, cut behandelt alle tekens als één kolom breed.

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

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

3. (Nog steeds geen) Internationalisering

Toen cut werd ontworpen, waren alle personages één byte lang en was internationalisering geen probleem. Toen schrijfsystemen met bredere karakters populair werden, was de oplossing die POSIX gebruikte om tussen de oude -c switch te dumpen, die zijn betekenis zou moeten behouden om karakters te selecteren , ongeacht het aantal bytes breed, en om een nieuwe switch -b te introduceren die selecteer bytes, ongeacht de huidige tekencodering. In de meeste populaire implementaties werd -b geïntroduceerd en werkt, maar -c werkt nog steeds precies zoals -b en niet zoals zou moeten. Bijvoorbeeld met GNU cut :

Het lijkt erop dat het spamfilter van SE Engelse teksten met geïsoleerde kanji-tekens op een zwarte lijst plaatst. Ik kon deze beperking niet overwinnen, dus de volgende voorbeelden zijn minder expressief dan ze zouden kunnen zijn.

  # 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...

Als je personages buiten het ASCII-bereik vallen en je wilt cut , moet je altijd rekening houden met de tekenbreedte in je codering en dienovereenkomstig -b gebruiken. Als en wanneer -c begint te werken zoals gedocumenteerd, hoeft u uw scripts niet te wijzigen.

4. Snelheidsvergelijkingen

cut 's beperkingen hebben mensen twijfelen aan het nut ervan. In feite kan dezelfde functionaliteit worden bereikt door krachtigere, meer populaire hulpprogramma's. Het voordeel van cut is echter de prestaties . Zie hieronder voor enkele snelheidsvergelijkingen. test.txt heeft drie miljoen regels, elk met vijf door spaties gescheiden velden. Voor de awk test werd mawk gebruikt, omdat het sneller is dan GNU awk . De shell zelf (laatste regel) is verreweg de slechtste speler. De opgegeven (in seconden) tijden zijn wat de time commando geeft als real time.

(Om misverstanden te voorkomen: alle geteste commando's gaven dezelfde output met de gegeven input, maar ze zijn natuurlijk niet equivalent en zouden verschillende outputs in verschillende situaties geven, met name als de velden werden gescheiden door een variabel aantal spaties)

Commando Tijd
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. Referentiële man-pagina's

Basis gebruik

Het typische gebruik is met CSV-type bestanden, waarbij elke regel bestaat uit velden gescheiden door een scheidingsteken, gespecificeerd door de optie -d . Het standaardscheidingsteken is het TAB-teken. Stel dat u een gegevensbestand data.txt met regels als

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

Vervolgens

# 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

Zoals gewoonlijk kunnen er optionele spaties zijn tussen een schakelaar en de parameter: -d, is hetzelfde als -d ,

GNU cut maakt het mogelijk om een --output-delimiter optie te specificeren: (een onafhankelijke eigenschap van dit voorbeeld is dat een puntkomma als input-scheidingsteken moet worden ontsnapt om zijn speciale behandeling door de shell te voorkomen)

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

Slechts één scheidingsteken

U kunt niet meer dan één scheidingsteken gebruiken: als u zoiets als -d ",;:" opgeeft, gebruiken sommige implementaties alleen het eerste teken als scheidingsteken (in dit geval de komma). Andere implementaties (bijv. GNU cut ) geven u een foutmelding.

$ 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.

Herhaalde scheidingstekens worden geïnterpreteerd als lege velden

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

is nogal voor de hand liggend, maar met door spaties gescheiden tekenreeksen is het misschien minder voor de hand liggend

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

cut kan niet worden gebruikt om argumenten te parseren, zoals de shell en andere programma's.

Geen citaat

Er is geen manier om het scheidingsteken te beschermen. Spreadsheets en vergelijkbare CSV-verwerkingssoftware herkennen meestal een tekstcitaat waarmee tekenreeksen met een scheidingsteken kunnen worden gedefinieerd. Met cut kan dat niet.

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

Extraheren, niet manipuleren

U kunt alleen delen van lijnen extraheren, velden niet opnieuw ordenen of herhalen.

$ 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow