Skip to main content
  • Home >
  • Documentation
  • FAQ
  • Downloads
  • Support
  • Current Release Notes
  • Ferret Users Guide
    • Users Guide Index
    • Commands Reference
    • 1. Introduction
    • 2. Data Set Basics
    • 3. Variables & Expressions
    • 4. Grids & Regions
    • 5. Animations & Gif Images
    • 6. Customizing Plots
    • 7. Handling String Data Symbols
    • 8. Working with Special Data Sets
    • 9. Computing Environment
    • 10. Converting to NetCDF
    • 11. Writing External Functions
    • Glossary
    • Appendix A: Functions
    • Appendix B: PPLUS Guide
    • Appendix C: Ferret-Specific PPLUS Enhancements
  • Previous Release Notes
  • Tutorials and Demos
    • Ferret Tour
    • DSG files: Discrete Sampling Geometries Demo
    • Ferret sorting demo
    • Fast Fourier Transforms demo
    • Empirical Orthogonal Functions demo
    • Ferret objective analysis demo
    • Ferret Palette Demo
    • Map projections
    • Ferret polygon vector demo
    • Ferret Graticules demo
    • Ferret Polytube Demo
    • Ferret Polymark Demo
    • Ferret Constant-Array demo
    • Ferret land_detail demo
    • COADS Tour
    • Levitus Tour
    • Use OPeNDAP
    • Ferret binary read demo
  • PyFerret
    • PyFerret Downloads and Install ../../faq/ferret-faqs.html
    • What is PyFerret?
    • Why use PyFerret?
    • PyFerret for the Ferret user
    • PyFerret command syntax: quick-start notes
    • PyFerret for the Python user
    • Graphics in PyFerret ?
    • New Ferret functionality
    • PyFerret Python functions and constants
    • PyFerret Python objects and methods
    • Ferret external functions in Python
    • Ferret Fortran external functions
    • PyFerret metadata-and-data dictionaries
  • OPeNDAP
    • OPeNDAP usage in Ferret
    • Use OPeNDAP Demo
    • Test OPeNDAP

7.2 STRING FUNCTIONS

A number of functions are available for working with string variables. They are described in the following sections. (See also the section later in this chapter, "PLOT+ string editing tools" for more ways to manipulate strings.)

7.2.1 STRCMP(string1, string2)

string1: string
string2: string
result: real

Compares two strings or string arrays. It computes the numerical difference in ASCII character value for the first character that differs between the two strings returns a number, > 0 if string1 > string2, 0 if they are equal and < 0 if string1 < string2.

Examples:

yes? list strcmp("b",{"a","b","c"})
VARIABLE : STRCMP("b",{"a","b","c"})
SUBSET : 3 points (X)
1 / 1: 1.000
2 / 2: 0.000
3 / 3: -1.000
 
yes? list strcmp({"a","b","c"},YSEQUENCE({"a","b","c"}))
VARIABLE : STRCMP({"a","b","c"},YSEQUENCE({"a","b","c"}))
SUBSET : 3 by 3 points (X-Y)
1 2 3 
1 2 3
1 / 1: 0.000 1.000 2.000
2 / 2: -1.000 0.000 1.000
3 / 3: -2.000 -1.000 0.000
 
yes? let a = "a longer string"
yes? list strcmp (a,"a longer stringg")
VARIABLE : STRCMP (a,"a longer stringg")
-103.0

 

 

7.2.2 STRLEN(string1)

 

 

string1: string
result: real

Returns the length of the string-type variable passed in string string1

Example:

yes? LET myfile = "/home/e1/data/coads_climatology.nc"
yes? LIST STRLEN(myfile)
VARIABLE : STRLEN(MYFILE)
34.00
 
yes? LET svar = {"aa", "bbb", "cccc"}
yes? LIST strlen(svar)
VARIABLE : STRLEN(SVAR)
SUBSET : 3 points (X)
1 / 1: 2.000
2 / 2: 3.000
3 / 3: 4.000
 

7.2.3 UPCASE(string1)

string1: string
result: string

Returns the string passed in string variable string1 in all upper case characters

yes? LET svar = {"aa", "bbb", "cccc"}
yes? list upcase(svar)
VARIABLE : UPCASE(SVAR)
SUBSET : 3 points (X)
1 / 1:"AA" 
2 / 2:"BBB" 
3 / 3:"CCCC"

7.2.4 DNCASE(string1)

string1: string
result: string

Returns the string passed in string string1 in all lower case characters

yes? LET svar = {"Boulder", "Seattle", "San Francisco"}
yes? LIST DNCASE(svar)
VARIABLE : DNCASE(SVAR)
SUBSET : 3 points (X)
1 / 1:"boulder" 
2 / 2:"seattle" 
3 / 3:"san francisco"

7.2.5 STRINDEX(string1, substring)

string1: string
substring: string
result: real

Locate first occurrence of substring in string1. Returns a 0 if substring doesn't exist in string1. If substring contains a zero-character string (i.e. ""), the function returns 1. The function is case-specific.

yes? LET myfile = "/home/e1/data/coads_climatology.nc"
yes? LIST STRINDEX(myfile, "coads")
VARIABLE : STRINDEX(MYFILE, "coads")
15.00
 
yes? LIST STRINDEX(myfile, "COADS")
VARIABLE : STRINDEX(MYFILE, "COADS")
0.0000
 

7.2.6 STRRINDEX(string1, substring)

string1: string
substring: string
result: real

Locates last occurence of string substring in string1. Returns a 0 if substring doesn't exist in string1. If substring contains a zero character string (i.e. ""), the function returns the length of string1

yes? LET myfile = "/home/e1/data/coads_climatology.nc"
yes? LIST STRRINDEX(myfile, "/")
VARIABLE : STRRINDEX(MYFILE, "/")
14.00

7.2.7 SUBSTRING(string1, offset, len)

string1: string
offset: integer
len: integer
result: string

Returns substring of length len from string string1 beginning from character offset in string1. If offset is 0, or if offset is greater than the length of string string1, a NULL value is returned. If length len exceeds the total length of string string1, the value of string string1 starting at offset is returned.

yes? LET myfile = "/home/e1/data/coads_climatology.nc"
yes? LET ns = STRRINDEX(myfile, "/")
VARIABLE : STRRINDEX(MYFILE, "/")
14.00
 
yes? LET path = SUBSTRING(myfile, 1, ns) 
yes? LIST path
VARIABLE : SUBSTRING(MYFILE, 1, NS)
/home/e1/data/
 

7.2.8 STRCAT(string1, str2)

string1: string
string2: string
result: string

Append a copy of string string2 onto string string1. As with other functions, the rules of conformability apply to the arguments.

yes? LET s1 = "hello "
yes? LET s2 = "world"
yes? LIST STRCAT (s1, s2)
VARIABLE : STRCAT (S1, S2)
hello world
 
yes? LET s1 = "hello "
yes? LET svar = {"Boulder", "Seattle", "San Francisco"}
yes? LIST STRCAT (s1, svar)
VARIABLE : STRCAT(S1, SVAR)
SUBSET : 3 points (X)
1 / 1:"hello Boulder" 
2 / 2:"hello Seattle" 
3 / 3:"hello San Francisco"
 

7.2.9 STRFLOAT(string1)

string1: string
result: real

Return float value of string string1

yes? LET pie = "3.14"
yes? LIST STRFLOAT (pie)yes? list strfloat(pie)
VARIABLE : STRFLOAT(PIE)
3.140
 

 

7.2.10 FLOATSTR(A, FMT)

A: numeric variable
FMT: string, the Fortran format specification.
result: string

Convert numeric data to strings using the specified Fortran format.

Examples:

yes? SHOW FUNCTION floatstr
FLOATSTR(A,FMT)
Returns float converted to strings according to format specified
A: Floating-point variable to convert
FMT: Fortran format, in parentheses, e.g. "(F5.1)" (STRING)
 
yes? LIST floatstr({3.14159,2.71828,10},"(f7.3)")
VARIABLE : FLOATSTR({3.14159,2.71828,10},"(f7.3)")
SUBSET : 3 points (X)
1 / 1:" 3.142"
2 / 2:" 2.718"
3 / 3:" 10.000"

 

yes? USE etopo60
yes? LIST floatstr(rose[y=60,x=-10:0], "(f6.0)")
VARIABLE : FLOATSTR(ROSE[Y=60,X=-10:0], "(f6.0)")
FILENAME : etopo60.cdf
FILEPATH : /home/porter/tmap/ferret/linux/fer_dsets/data/
SUBSET : 10 points (LONGITUDE)
LATITUDE : 59.5N
59.5N 
150
9.5W / -29:"-1327."
8.5W / -28:"-1245."
7.5W / -27:" -869."
6.5W / -26:" -444."
5.5W / -25:" -260."
4.5W / -24:" -130."
3.5W / -23:" -93."
2.5W / -22:" -67."
1.5W / -21:" -90."
0.5W / -20:" -115."

 

 

yes? USE coads_climatology
yes? LIST floatstr(sst[x=10:20,y=60,L=1], "(g8.3)")
VARIABLE : FLOATSTR(SST[X=10:20,Y=60,L=1], "(g8.3)")
FILENAME : coads_climatology.cdf
FILEPATH : /home/porter/tmap/ferret/linux/fer_dsets/data/
SUBSET : 6 points (LONGITUDE)
LATITUDE : 59N
TIME : 16-JAN 06:00
59N 
75
11E / -4:"3.36"
13E / -3:"" 
15E / -2:"" 
17E / -1:"2.32"
19E / 0:"2.69"
21E / 1:"2.90"

Notes:

1) The Fortran format in argument 2 must be a numeric format (as is the case for LIST/FORMAT). F, G, E, I, and D formats are allowed. "A" formats are not allowed. Prior to Ferret v6.95, Integer formats were not allowed.

In addition, zero-filled output may be requested using a modified F-format specifier. If F is followed by a 0, the result is zero-filled.

Examples:

yes? LIST FLOATSTR({3.14,2.72},"(I3)")
VARIABLE : FLOATSTR({3.14,2.72},"(I3)")
SUBSET   : 2 points (X)
1   / 1:"  3"
2   / 2:"  2"
 
 
yes? list FLOATSTR({3.14,2.72},"(I4.4)")
VARIABLE : FLOATSTR({3.14,2.72},"(I4.4)")
SUBSET : 2 points (X)
1 / 1:"0003"
2 / 2:"0002"
 
 
yes? list FLOATSTR({3.14,2.72},"(F6.2)")
VARIABLE : FLOATSTR({3.14,2.72},"(F6.2)")
SUBSET   : 2 points (X)
1   / 1:"  3.14"
2   / 2:"  2.72"
 
 
yes? list FLOATSTR({3.14159,2.71828},"(F06.2)")
VARIABLE : FLOATSTR({3.14159,2.71828},"(F06.2)")
SUBSET   : 2 points (X)
1   / 1:"003.14"
2   / 2:"002.72"

2) Missing data in the numeric variable is converted by FLOATSTR to the null string.

 

7.2.11 LABWID(string, charsize)

 

string: string, possibly including a font specification, and may include <NL> newline character
charsize: real

result: real

Returns the size in plot-page inches of the string. If a font is specified, it takes the size of characters in that font into account. If the string is a multi-line label, the result is computed for the longest line as it will appear on the plot page.

Examples:

! LABWID with two different character sizes,
! lowercase vs capitals, and the italics font
 
yes? LIST/NOHEADER LABWID("abcdefg", .15)
0.8857
yes? LIST/NOHEADER LABWID("abcdefg", .10)
0.5905
yes? LIST/NOHEADER LABWID("ABCDEFG", .15)
0.9929
yes? LIST/NOHEADER LABWID("@IIabcdefg", .15)
1.0000
 
! multi-line label: result is the length of the longest line
yes? LIST/NOHEADER LABWID("abcdefg<NL>hi", .15)
0.8857
 
! Make a plot, drawing one label after another.
! Use the italics font for the first label.
 
yes? PLOT/VS/LINE/I=1:314 i*cos(i/20),i*sin(i/20)
 
yes? LET firstlab = "@iiMy label"
yes? LABEL/NOUSER 0, 3, -1, 0, .15, "`firstlab`"
yes? LET wid = labwid("`firstlab`", .15)
yes? LABEL/NOUSER `wid`, 3, -1, 0, .15, "@P4Second Label"

 

 

7.2.12 SPAWN command

The SPAWN command executes a Unix system command and returns the result in a string array. The syntax SPAWN:"command" inside a string array definition allows the output of a Unix command to be mixed with other strings.

SPAWN commands are disallowed when Ferret was started in secure mode with

> ferret -secure

 

Examples:

LET a = {"first.nc", SPAWN:"ls *.nc","last.nc"}

Say we want to check whether a file is in the directory. We do not want a null result, so start with a dummy string. If "myfile.nc" exists, there will be 2 entries in array a.

yes? LET a = {"dummy", SPAWN:"ls myfile.nc"}
yes? LET nfiles = `a[i=@ngd]`
yes? IF `nfiles EQ 2` THEN ..

7.2.12.1 SPAWN Function

The SPAWN function executes a Unix system command or set of commands, and returns the result in a string array. Each element of the result is a line of the output.
 

The SPAWN function is disallowed when Ferret was started in secure mode with

> ferret -secure

Examples:

yes? LET lengths = SPAWN("wc *.jnl")
 
yes? LET who_where_when = SPAWN("whoami; pwd; date")
 

 

 

 

 

 

 

7.2.13 Algebraic operations with string variables.

A number of algebraic operations are available for string variables. They are described in the following sections.

 

7.2.13.1 Logical operators with strings

 

The operators EQ, LT, LE, .. can be applied to string variables and arrays. These operators are case-insensitive (functions will be provided later that are case-sensitive and include UPCASE, DNCASE)

Examples:

yes? LIST/NOHEAD {"a","b","c"} EQ {"A","B","C"} ! case insensitive
1 / 1: 1.000
2 / 2: 1.000
3 / 3: 1.000
yes? LIST/NOHEAD "b" GT {"a","b","c"}
1 / 1: 1.000
2 / 2: 0.000
3 / 3: 0.000

 

 

7.2.13.2 Shift transformation of string arrays

 

 

The shift transformation can be applied to string arrays.

For example:

yes? LET a = {"a","b","c","d"}
yes? LIST a[i=@SHF]
{"a","b","c","d"}
shifted by 1 pts on X
1 / 1:"b"
2 / 2:"c"
3 / 3:"d"
4 / 4:"" 
yes? LIST a[i=@SHF:-1]
{"a","b","c","d"}
shifted by -1 pts on X
1 / 1:"" 
2 / 2:"a"
3 / 3:"b"
4 / 4:"c"

 

 

7.2.13.3 Strings in IF-THEN-ELSE

IF condition THEN string_array1 ELSE string_array2

Example:

yes? LIST/NOHEAD IF {0,1} THEN "hello" ELSE "goodbye"
1 / 1:"goodbye"
2 / 2:"hello"

 

 

7.2.13.4 String concatenation with "+":

String variables may be concatenated with the XCAT, YCAT, ZCAT or TCAT functions.
This may also be done with the addition operator:

Examples:

yes? LET a = "good" + "bye"
yes? LIST/NOHEAD YSEQUENCE({"now","then"})+", " + (if {0,1} THEN "hello"+", ") + "friend"
1 / 1:"now, friend" "now, hello, friend" 
2 / 2:"then, friend" "then, hello, friend"

 

7.2.13.5 Strings as Function arguments

A few functions also take strings as arguments. String arguments must be enclosed in double quotes. For example, the TAX_DATESTRING allows a customized output precision, set by the last argument.

yes? list tax_datestring(date_list,t[gt=tax], "day")

SAMPLE* functions may take string or numerical arrays as arguments

Example:

yes? LIST/NOHEAD SAMPLEI({"a","b","c","d","e","f"},{3,2,,1})
1 / 1:"c"
2 / 2:"b"
3 / 3:"" 
4 / 4:"a"
 
yes? LIST/NOHEAD SAMPLEJ(YSEQUENCE ({"a","b","c","d","e","f"}), {3,2,,1})
1 / 1:"c"
2 / 2:"b"
3 / 3:"" 
4 / 4:"a"

 

 

7.2.13.6 Regridding string arrays

 

 

The regridding transformations @ASN, @XACT, @NRST can be used with character data.

Examples:

yes? LET a = {spawn:"ls *.nc"}
yes? LIST a
{SPAWN:"ls *.nc"}
1 / 1:"d1.nc"
2 / 2:"d2.nc"
3 / 3:"d3.nc"
4 / 4:"d4.nc"
5 / 5:"d5.nc"
6 / 6:"d6.nc"
7 / 7:"d7.nc"
 
yes? DEFINE AXIS/X=0.1:0.7:.1 xasn
yes? LIST a[gx=xasn@ASN]
{SPAWN:"ls *.nc"}
regrid: 0.1 delta on X@ASN
0.1 / 1:"d1.nc"
0.2 / 2:"d2.nc"
0.3 / 3:"d3.nc"
0.4 / 4:"d4.nc"
0.5 / 5:"d5.nc"
0.6 / 6:"d6.nc"
0.7 / 7:"d7.nc"
 
yes? DEFINE AXIS/X=1:6:.5 xxact
yes: LIST a[gx=xxact@XACT]
{SPAWN:"ls *.nc"}
regrid: 0.5 delta on X@XACT
1 / 1:"d1.nc"
1.5 / 2:"" 
2 / 3:"d2.nc"
2.5 / 4:"" 
3 / 5:"d3.nc"
3.5 / 6:"" 
4 / 7:"d4.nc"
4.5 / 8:"" 
5 / 9:"d5.nc"
5.5 / 10:"" 
6 / 11:"d6.nc"
 
yes? DEFINE AXIS/X=1:6:.4 xnrst
yes? LIST a[gx=xnrst@NRST]
{SPAWN:"ls *.nc"}
regrid: 0.4 delta on X@NRST
1 / 1:"d1.nc"
1.4 / 2:"d1.nc"
1.8 / 3:"d2.nc"
2.2 / 4:"d2.nc"
2.6 / 5:"d3.nc"
3 / 6:"d3.nc"
3.4 / 7:"d3.nc"
3.8 / 8:"d4.nc"
4.2 / 9:"d4.nc"
4.6 / 10:"d5.nc"
5 / 11:"d5.nc"
5.4 / 12:"d5.nc"
5.8 / 13:"d6.nc"
6.2 / 14:"d6.nc"

 

 

 

 

7.2.14 NetCDF input and output of string data

String variables can be input and output to netCDF files. In the file the string axis is the fastest moving dimension and all strings are the same length (equal to the maximum length of the strings being written). Extra character spaces are padded with nulls. If variable length strings are written out, then when read back they will again be variable length.

Example:

yes? SAVE/CLOBBER/FILE=test_string.cdf/HEADING=enhanced a[i=2:4]

 

 

7.2.15 Transformations on string data

 

 

The transformations @NGD and @NBD can be used to compute the number of valid and invalid strings. The null string is taken to be the "missing value" for string data.

yes? LET svar = {"Boulder", "Seattle", , "San Francisco"}
yes? LIST svar[i=@ngd]
*** NOTE: @NGD of string variable, counting null strings as missing
VARIABLE : {"Boulder", "Seattle", , "San Francisco"} (# of points)
X : 0.5 to 4.5 (number of valid)
3.000
 
yes? LIST svar[i=@nbd]
*** NOTE: @NBD of string variable, counting null strings as missing
VARIABLE : {"Boulder", "Seattle", , "San Francisco"} (# of points)
X : 0.5 to 4.5 (number flagged bad)
1.000
 
! This is the same as,
yes? LET svar = {"Boulder", "Seattle", "", "San Francisco"}
 

7.2.16 Further functions

String versions of some other functions are available. Please see the documentation on each function. These include

XCAT, YCAT, ZCAT, TCAT, Concatenation functions which detect the data type of their argument and work accordingly

XSORT, YSORT, ZSORT, TSORT, which also detect the data type of their arguments. Recall that the SORT commands return the index values of the sorted data.

SAMPLEI, SAMPLEJ, SAMPLEK, SAMPLEL, which also detect the data type of their arguments.

IS_ELEMENT_OF_STR Returns the index value in argument 2 for each string in argument 1

IS_ELEMENT_OF_STR Returns 1 if first argument contains any of the values in 2nd argument